Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/GeneralCombiner.cpp
2 views
1
/*
2
Copyright (C) 2003 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 "Debugger.h"
24
25
extern const int numOf3StageCombiners;
26
extern const int numOf2StageCombiners;
27
extern GeneralCombinerInfo CombinerTable2Stages[];
28
extern GeneralCombinerInfo CombinerTable3Stages[];
29
30
CGeneralCombiner::CGeneralCombiner()
31
{
32
m_lastGeneralIndex=0;
33
m_ppGeneralDecodedMux=NULL;
34
35
m_bTxtOpAdd=true;
36
m_bTxtOpSub=false;
37
m_bTxtOpLerp=false;
38
m_bTxtOpAddSmooth=false;
39
m_bTxtOpBlendCurAlpha=false;
40
m_bTxtOpBlendDifAlpha=true;
41
m_bTxtOpBlendFacAlpha=false;
42
m_bTxtOpBlendTxtAlpha=true;
43
m_bTxtOpMulAdd=false;
44
45
m_dwGeneralMaxStages=2;
46
}
47
48
bool isTex(uint32 val)
49
{
50
return ( (val&MUX_MASK) == MUX_TEXEL0 || (val&MUX_MASK) == MUX_TEXEL1 );
51
}
52
int toTex(uint32 val)
53
{
54
return (val&MUX_MASK)-MUX_TEXEL0;
55
}
56
57
bool isComb(uint32 val)
58
{
59
return (val&MUX_MASK)==MUX_COMBINED;
60
}
61
62
#ifdef DEBUGGER
63
const char* BlendFuncStr[] = {
64
"Enable both",
65
"Disable alpha",
66
"Disable color",
67
"Disable both",
68
"Color one",
69
"Alpha one",
70
};
71
const char* cmopstrs[] = {
72
"Sel",
73
"Mod",
74
"Add",
75
"Sub",
76
"Lerp",
77
"AddSmooth",
78
"BlCurA",
79
"BlDifA",
80
"BlFacA",
81
"BlTexA",
82
"MulAdd",
83
};
84
85
void CGeneralCombiner::General_DisplayBlendingStageInfo(GeneralCombinerInfo &gci)
86
{
87
char str1[30],str2[30],str3[30];
88
DebuggerAppendMsg("\nStages:%d, Alpha:%s, Factor:%s, Specular:%s Dif Color:0x%X Dif Alpha:0x%X\n",
89
gci.nStages, BlendFuncStr[gci.blendingFunc], DecodedMux::FormatStr((uint8)gci.TFactor,str1),
90
DecodedMux::FormatStr((uint8)gci.specularPostOp,str2), gci.m_dwShadeColorChannelFlag, gci.m_dwShadeAlphaChannelFlag);
91
92
for( int i=0; i<gci.nStages; i++ )
93
{
94
GeneralCombineStage &s = gci.stages[i];
95
DebuggerAppendMsg("%d:Color: %s - %s, %s, %s%s\n", i,
96
cmopstrs[s.colorOp.op], DecodedMux::FormatStr((uint8)s.colorOp.Arg1, str1), s.colorOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg2, str2),
97
s.colorOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.colorOp.Arg0, str3),
98
s.dwTexture!=0?" -Tex1":"");
99
}
100
101
for( int i=0; i<gci.nStages; i++ )
102
{
103
GeneralCombineStage &s = gci.stages[i];
104
DebuggerAppendMsg("%d:Alpha: %s - %s, %s, %s%s\n", i,
105
cmopstrs[s.alphaOp.op], DecodedMux::FormatStr((uint8)s.alphaOp.Arg1, str1),
106
s.alphaOp.Arg2==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg2, str2),
107
s.alphaOp.Arg0==CM_IGNORE?"":DecodedMux::FormatStr((uint8)s.alphaOp.Arg0, str3),
108
s.dwTexture!=0?" -Tex1":"");
109
}
110
TRACE0("\n\n");
111
}
112
#endif
113
114
115
///////////////////////////////////////
116
// Combiner gci generating functions //
117
///////////////////////////////////////
118
119
bool textureUsedInStage[8][2];
120
bool resultIsGood;
121
122
void CGeneralCombiner::GenCI_Init(GeneralCombinerInfo &gci)
123
{
124
gci.specularPostOp=gci.TFactor=MUX_0;
125
126
gci.blendingFunc = ENABLE_BOTH;
127
resultIsGood = true;
128
129
//After the mux is reformated and simplified, we can use it to generate combine stages
130
//return false if we can not generate it
131
132
for( int i=0; i<8; i++)
133
{
134
gci.stages[i].dwTexture = 0;
135
textureUsedInStage[i][0] = false; // For color
136
textureUsedInStage[i][1] = false; // For alpha
137
gci.stages[i].bTextureUsed = false;
138
gci.stages[i].dwTexture = 0;
139
gci.stages[i].colorOp.op = gci.stages[i].alphaOp.op = CM_REPLACE;
140
gci.stages[i].colorOp.Arg1 = gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;
141
gci.stages[i].colorOp.Arg2 = gci.stages[i].alphaOp.Arg2 = CM_IGNORE;
142
gci.stages[i].colorOp.Arg0 = gci.stages[i].alphaOp.Arg0 = CM_IGNORE;
143
}
144
145
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
146
147
// Check some special cases of alpha channel
148
if( mux.splitType[N64Cycle0Alpha]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_NOT_USED )
149
{
150
//if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_0 )
151
// gci.blendingFunc = DISABLE_COLOR;
152
//else
153
if( mux.m_n64Combiners[N64Cycle0Alpha].d == MUX_1 )
154
gci.blendingFunc = DISABLE_ALPHA;
155
}
156
else if( mux.splitType[N64Cycle1Alpha]==CM_FMT_TYPE_D )
157
{
158
//if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_0 )
159
// gci.blendingFunc = DISABLE_COLOR;
160
//else
161
if( mux.m_n64Combiners[N64Cycle1Alpha].d == MUX_1 )
162
gci.blendingFunc = DISABLE_ALPHA;
163
}
164
165
if( mux.splitType[N64Cycle0RGB]==CM_FMT_TYPE_D && mux.splitType[N64Cycle1RGB]==CM_FMT_TYPE_NOT_USED )
166
{
167
if( mux.m_n64Combiners[N64Cycle0RGB].d == MUX_0 )
168
gci.blendingFunc = DISABLE_COLOR;
169
}
170
171
}
172
173
int CGeneralCombiner::GenCI_Type_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
174
{
175
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
176
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
177
if( ( m.d == MUX_0 || m.d == MUX_1 ) && curN64Stage==1 )
178
{
179
//if( m.d == MUX_0 )
180
// gci.blendingFunc = DISABLE_COLOR;
181
//if( m.d == MUX_1 )
182
// gci.blendingFunc = DISABLE_ALPHA;
183
184
op->op = CM_REPLACE;
185
op->Arg1 = MUX_COMBINED;
186
op->Arg2 = CM_IGNORE;
187
op->Arg0 = CM_IGNORE;
188
}
189
else
190
{
191
if( isTex(m.d) ) Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.d));
192
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
193
194
op->op = CM_REPLACE;
195
op->Arg1 = m.d;
196
op->Arg2 = CM_IGNORE;
197
op->Arg0 = CM_IGNORE;
198
}
199
200
if( !gci.stages[curStage].bTextureUsed )
201
gci.stages[curStage].dwTexture = GetTexelNumber(m);
202
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);
203
return curStage;
204
}
205
206
int CGeneralCombiner::GenCI_Type_A_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci, uint32 dxop)
207
{
208
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
209
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
210
211
if( CountTexel1Cycle(m) == 2 )
212
{
213
// As we can not use both texture in one stage
214
// we split them to two stages
215
// Stage1: SELECT txt1
216
// Stage2: MOD txt2
217
218
if( gci.stages[curStage].bTextureUsed && gci.stages[curStage].dwTexture != (unsigned int)toTex(m.a) )
219
swap(m.a,m.c);
220
221
op->op =CM_REPLACE;
222
op->Arg1 = m.a;
223
op->Arg2 = CM_IGNORE;
224
op->Arg0 = CM_IGNORE;
225
gci.stages[curStage].dwTexture = toTex(m.a);
226
textureUsedInStage[curStage][curN64Stage%2] = true;
227
228
NextStage(curStage);
229
Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.c));
230
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
231
232
op->op =dxop;
233
op->Arg1 = (m.c);
234
op->Arg2 = MUX_COMBINED;
235
op->Arg0 = CM_IGNORE;
236
gci.stages[curStage].dwTexture = toTex(m.c);
237
textureUsedInStage[curStage][curN64Stage%2] = true;
238
}
239
else
240
{
241
if( CountTexel1Cycle(m) == 1)
242
{
243
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
244
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
245
}
246
247
op->op = dxop;
248
op->Arg1 = (m.a);
249
op->Arg2 = (m.c);
250
op->Arg0 = CM_IGNORE;
251
if( !gci.stages[curStage].bTextureUsed )
252
gci.stages[curStage].dwTexture = GetTexelNumber(m);
253
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);
254
}
255
256
return curStage;
257
}
258
int CGeneralCombiner::GenCI_Type_A_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
259
{
260
uint32 opToUse = m_bTxtOpAdd?CM_ADD:CM_MODULATE;
261
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
262
swap(m.c, m.d);
263
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci, opToUse);
264
swap(m.c, m.d);
265
return curStage;
266
}
267
268
int CGeneralCombiner::GenCI_Type_A_SUB_B(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
269
{
270
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
271
if( !m_bTxtOpSub )
272
{
273
swap(m.c, m.b);
274
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);
275
swap(m.c, m.b);
276
return curStage;
277
}
278
279
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
280
281
if( CountTexel1Cycle(m) == 2 )
282
{
283
Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.b));
284
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
285
286
op->op =CM_REPLACE;
287
op->Arg1 = (m.b);
288
op->Arg2 = CM_IGNORE;
289
op->Arg0 = CM_IGNORE;
290
gci.stages[curStage].dwTexture = toTex(m.b);
291
textureUsedInStage[curStage][curN64Stage%2] = true;
292
293
NextStage(curStage);
294
Check1TxtrForAlpha(curN64Stage, curStage, gci, toTex(m.a));
295
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
296
297
op->op =CM_SUBTRACT;
298
op->Arg1 = (m.a);
299
op->Arg2 = MUX_COMBINED;
300
op->Arg0 = CM_IGNORE;
301
gci.stages[curStage].dwTexture = toTex(m.a);
302
textureUsedInStage[curStage][curN64Stage%2] = true;
303
}
304
else
305
{
306
if( CountTexel1Cycle(m) == 1)
307
{
308
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
309
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
310
}
311
312
op->op = CM_SUBTRACT;
313
op->Arg1 = (m.a);
314
op->Arg2 = (m.b);
315
op->Arg0 = CM_IGNORE;
316
if( !gci.stages[curStage].bTextureUsed )
317
gci.stages[curStage].dwTexture = GetTexelNumber(m);
318
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);
319
}
320
return curStage;
321
}
322
323
int CGeneralCombiner::GenCI_Type_A_MOD_C_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
324
{
325
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
326
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
327
328
if( !m_bTxtOpMulAdd )
329
{
330
N64CombinerType save = m;
331
m.d = MUX_0;
332
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);
333
m = save;
334
m.c = MUX_0;
335
m.a = MUX_COMBINED;
336
NextStage(curStage);
337
curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);
338
m = save;
339
return curStage;
340
}
341
342
if( CountTexel1Cycle(m) == 2 )
343
{
344
if( !gci.stages[curStage].bTextureUsed )
345
{
346
gci.stages[curStage].dwTexture = 0;
347
gci.stages[curStage].bTextureUsed = true;
348
}
349
350
op->op = CM_REPLACE;
351
op->Arg2 = CM_IGNORE;
352
op->Arg0 = CM_IGNORE;
353
op->Arg1 = MUX_TEXEL0 + gci.stages[curStage].dwTexture ;
354
355
N64CombinerType m2 = m;
356
357
uint8* vals = (uint8*)&m2;
358
for( int i=0; i<4; i++ )
359
{
360
if( (unsigned int)(vals[i]&MUX_MASK) == MUX_TEXEL0 + gci.stages[curStage].dwTexture )
361
{
362
vals[i] = MUX_COMBINED | (vals[i]&0xe0);
363
}
364
}
365
366
NextStage(curStage);
367
368
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m2));
369
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
370
371
op->op = CM_MULTIPLYADD;
372
op->Arg1 = m2.a;
373
op->Arg2 = m2.c;
374
op->Arg0 = m2.d;
375
if( !gci.stages[curStage].bTextureUsed )
376
gci.stages[curStage].dwTexture = GetTexelNumber(m2);
377
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m2);
378
}
379
else
380
{
381
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
382
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
383
384
op->op = CM_MULTIPLYADD;
385
op->Arg1 = (m.a);
386
op->Arg2 = (m.c);
387
op->Arg0 = (m.d);
388
if( !gci.stages[curStage].bTextureUsed )
389
gci.stages[curStage].dwTexture = GetTexelNumber(m);
390
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);
391
}
392
393
return curStage;
394
}
395
396
397
int CGeneralCombiner::GenCI_Type_A_LERP_B_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
398
{
399
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
400
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
401
402
N64CombinerType save = m;
403
404
if( CountTexel1Cycle(m) == 2 )
405
{
406
// There are two textures
407
int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci);
408
op->op =CM_REPLACE;
409
op->Arg1 = (MUX_TEXEL0+texToUse);
410
op->Arg2 = CM_IGNORE;
411
op->Arg0 = CM_IGNORE;
412
gci.stages[curStage].dwTexture = texToUse;
413
textureUsedInStage[curStage][curN64Stage%2] = true;
414
415
(*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage);
416
NextStage(curStage);
417
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
418
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
419
}
420
421
// Now we have only 1 texture left
422
423
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
424
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
425
426
if( m.a == MUX_1 )
427
{
428
op->op = CM_ADDSMOOTH;
429
op->Arg1 = (m.b);
430
op->Arg2 = (m.c);
431
op->Arg0 = CM_IGNORE;
432
}
433
else if( m.a == MUX_0 )
434
{
435
op->op = CM_MODULATE;
436
m.a = 0;
437
op->Arg1 = (m.b);
438
op->Arg2 = (m.c^MUX_COMPLEMENT);
439
op->Arg0 = CM_IGNORE;
440
}
441
else
442
{
443
if( ((m.c&MUX_ALPHAREPLICATE) || (curN64Stage%2)==1 || m_bTxtOpLerp == false) && ((m.c&MUX_MASK)==MUX_SHADE || (m.c&MUX_MASK)==MUX_COMBINED || (m.c&MUX_MASK)==MUX_TEXEL0 || (m.c&MUX_MASK)==MUX_TEXEL1 ) )
444
{
445
if( curN64Stage == 2 && (m.c&MUX_ALPHAREPLICATE) == 0 )
446
{
447
op->op = CM_MODULATE;
448
op->Arg1 = m.b;
449
op->Arg2 = m.c|MUX_COMPLEMENT;
450
op->Arg0 = CM_IGNORE;
451
resultIsGood = false;
452
}
453
else
454
{
455
if( (m.c&MUX_MASK)==MUX_SHADE )
456
{
457
op->op = CM_BLENDDIFFUSEALPHA;
458
}
459
else if( (m.c&MUX_MASK) == MUX_COMBINED )
460
{
461
op->op = CM_BLENDCURRENTALPHA;
462
}
463
else if( (m.c&MUX_MASK) == MUX_TEXEL0 )
464
{
465
op->op = CM_BLENDTEXTUREALPHA;
466
}
467
else if( (m.c&MUX_MASK)==MUX_TEXEL1 )
468
{
469
op->op = CM_BLENDTEXTUREALPHA;
470
}
471
else
472
{
473
op->op = CM_BLENDDIFFUSEALPHA;
474
}
475
op->Arg1 = (m.a);
476
op->Arg2 = (m.b);
477
op->Arg0 = m.c|MUX_ALPHAREPLICATE;
478
}
479
}
480
else
481
{
482
if( ((m.c&MUX_ALPHAREPLICATE) || (curN64Stage%2)==1 || m_bTxtOpLerp == false) && ((((m.c&MUX_MASK)==MUX_ENV) || ((m.c&MUX_MASK)==MUX_PRIM)) ))
483
{
484
op->op = CM_BLENDFACTORALPHA;
485
op->Arg1 = (m.a);
486
op->Arg2 = (m.b);
487
op->Arg0 = m.c|MUX_ALPHAREPLICATE;
488
}
489
else
490
{
491
op->op = CM_INTERPOLATE;
492
op->Arg0 = (m.c);
493
op->Arg1 = (m.a);
494
op->Arg2 = (m.b);
495
}
496
}
497
}
498
gci.stages[curStage].dwTexture = GetTexelNumber(m);
499
textureUsedInStage[curStage][curN64Stage%2] = IsTxtrUsed(m);
500
501
m = save;
502
return curStage;
503
}
504
505
506
int CGeneralCombiner::GenCI_Type_A_B_C_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
507
{
508
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
509
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
510
511
N64CombinerType save = m;
512
if( CountTexel1Cycle(m) == 2 )
513
{
514
if( isTex(m.a) && !isTex(m.c) && curN64Stage == 0 && isTex(m.d) && toTex(m.a) != toTex(m.d) )
515
{
516
if( m_dwGeneralMaxStages >= 4 )
517
{
518
op->op = CM_SUBTRACT;
519
op->Arg1 = m.a;
520
op->Arg2 = m.b;
521
op->Arg0 = CM_IGNORE;
522
gci.stages[curStage].dwTexture = toTex(m.a);
523
textureUsedInStage[curStage][curN64Stage%2] = true;
524
NextStage(curStage);
525
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
526
op->op = CM_MULTIPLYADD;
527
op->Arg1 = MUX_COMBINED;
528
op->Arg2 = m.c;
529
op->Arg0 = m.d;
530
gci.stages[curStage].dwTexture = toTex(m.d);
531
textureUsedInStage[curStage][curN64Stage%2] = true;
532
resultIsGood = true;
533
}
534
else
535
{
536
op->op = CM_MODULATE;
537
op->Arg1 = m.a;
538
op->Arg2 = m.c;
539
op->Arg0 = CM_IGNORE;
540
gci.stages[curStage].dwTexture = toTex(m.a);
541
textureUsedInStage[curStage][curN64Stage%2] = true;
542
NextStage(curStage);
543
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
544
op->op = CM_ADD;
545
op->Arg1 = MUX_COMBINED;
546
op->Arg2 = m.d;
547
op->Arg0 = CM_IGNORE;
548
gci.stages[curStage].dwTexture = toTex(m.d);
549
textureUsedInStage[curStage][curN64Stage%2] = true;
550
resultIsGood = false;
551
}
552
}
553
else
554
{
555
// There are two textures
556
int texToUse = CheckWhichTexToUseInThisStage(curN64Stage, curStage, gci);
557
op->op =CM_REPLACE;
558
op->Arg1 = (MUX_TEXEL0+texToUse);
559
op->Arg2 = CM_IGNORE;
560
op->Arg0 = CM_IGNORE;
561
gci.stages[curStage].dwTexture = texToUse;
562
textureUsedInStage[curStage][curN64Stage%2] = true;
563
564
(*m_ppGeneralDecodedMux)->ReplaceVal(MUX_TEXEL0+texToUse, MUX_COMBINED, curN64Stage);
565
566
NextStage(curStage);
567
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
568
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + (curN64Stage%2);
569
570
m.a = MUX_COMBINED;
571
m.c = MUX_TEXEL0+(1-texToUse);
572
m.b = m.d = 0;
573
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);
574
}
575
}
576
else if( CountTexel1Cycle(m) == 1 )
577
{
578
if( m_dwGeneralMaxStages < 4 )
579
{
580
Check1TxtrForAlpha(curN64Stage, curStage, gci, GetTexelNumber(m));
581
op->Arg1 = (MUX_TEXEL0+GetTexelNumber(m));
582
if( (*m_ppGeneralDecodedMux)->isUsedInCycle(MUX_SHADE, curN64Stage) )
583
{
584
op->op =CM_MODULATE;
585
op->Arg2 = MUX_SHADE;
586
}
587
else
588
{
589
op->op =CM_REPLACE;
590
op->Arg2 = 0;
591
}
592
op->Arg0 = CM_IGNORE;
593
gci.stages[curStage].dwTexture = GetTexelNumber(m);
594
textureUsedInStage[curStage][curN64Stage%2] = true;
595
}
596
else
597
{
598
curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci);
599
m.a = MUX_COMBINED;
600
NextStage(curStage);
601
curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);
602
}
603
}
604
else
605
{
606
m.d = 0;
607
curStage = GenCI_Type_A_SUB_B_MOD_C(curN64Stage, curStage, gci);
608
m = save;
609
m.a = MUX_COMBINED;
610
m.b = m.c = 0;
611
NextStage(curStage);
612
curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);
613
}
614
615
m = save;
616
return curStage;
617
}
618
619
int CGeneralCombiner::GenCI_Type_A_SUB_B_ADD_D(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
620
{
621
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
622
623
N64CombinerType save = m;
624
m.d = MUX_0;
625
curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci);
626
m = save;
627
m.a = MUX_COMBINED;
628
m.b = MUX_0;
629
NextStage(curStage);
630
curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);
631
m = save;
632
633
return curStage;
634
}
635
636
637
int CGeneralCombiner::GenCI_Type_A_ADD_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
638
{
639
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
640
641
N64CombinerType save = m;
642
m.d = m.b; m.b = 0;
643
curStage = GenCI_Type_A_ADD_D(curN64Stage, curStage, gci);
644
m = save;
645
m.b = MUX_0;
646
m.a = MUX_COMBINED;
647
NextStage(curStage);
648
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);
649
m = save;
650
651
return curStage;
652
}
653
654
int CGeneralCombiner::GenCI_Type_A_B_C_A(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
655
{
656
// We can not do too much with this type, it is not a bad idea to use LERP to simplify it.
657
//return GenCI_Type_A_LERP_B_C(curN64Stage, curStage, gci);
658
return GenCI_Type_A_B_C_D(curN64Stage, curStage, gci);
659
}
660
661
int CGeneralCombiner::GenCI_Type_A_SUB_B_MOD_C(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
662
{
663
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
664
665
N64CombinerType save = m;
666
m.c = MUX_0;
667
curStage = GenCI_Type_A_SUB_B(curN64Stage, curStage, gci);
668
m = save;
669
m.b = MUX_0;
670
m.a = MUX_COMBINED;
671
NextStage(curStage);
672
curStage = GenCI_Type_A_MOD_C(curN64Stage, curStage, gci);
673
m = save;
674
675
return curStage;
676
}
677
678
/////////////////////////////////////
679
// End of gci generating functions //
680
/////////////////////////////////////
681
682
683
void CGeneralCombiner::SkipStage(StageOperate &op, int &curStage)
684
{
685
op.op = CM_REPLACE;
686
op.Arg1 = MUX_COMBINED;
687
op.Arg2 = CM_IGNORE;
688
op.Arg0 = CM_IGNORE;
689
NextStage(curStage);
690
}
691
692
void CGeneralCombiner::NextStage(int &curStage)
693
{
694
if( curStage < m_dwGeneralMaxStages-1 )
695
{
696
curStage++;
697
}
698
else
699
{
700
curStage++;
701
resultIsGood = false;
702
TRACE0("Stage overflow");
703
}
704
}
705
706
void CGeneralCombiner::Check1TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex)
707
{
708
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
709
if( curN64Stage%2 && IsTxtrUsed(m) )
710
{
711
while (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)(tex) )
712
{
713
StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];
714
SkipStage(op, curStage);
715
}
716
}
717
}
718
719
720
int CGeneralCombiner::Check2TxtrForAlpha(int curN64Stage, int &curStage, GeneralCombinerInfo &gci, int tex1, int tex2)
721
{
722
N64CombinerType &m = (*m_ppGeneralDecodedMux)->m_n64Combiners[curN64Stage];
723
if( curN64Stage%2 && IsTxtrUsed(m) )
724
{
725
if( tex1 == tex2 )
726
{
727
while (curStage<m_dwGeneralMaxStages-1 && textureUsedInStage[curStage][0] && gci.stages[curStage].dwTexture != (unsigned int)tex1 )
728
{
729
StageOperate &op = ((StageOperate*)(&(gci.stages[curStage].colorOp)))[curN64Stage%2];
730
SkipStage(op, curStage);
731
}
732
return 1;
733
}
734
else
735
{
736
int stage1 = curStage;
737
int stage2 = curStage;
738
739
while (stage1<m_dwGeneralMaxStages-1 && textureUsedInStage[stage1][0] && gci.stages[stage1].dwTexture != (unsigned int)tex1 )
740
{
741
StageOperate &op = ((StageOperate*)(&(gci.stages[stage1].colorOp)))[curN64Stage%2];
742
SkipStage(op, stage1);
743
}
744
745
while (stage2<m_dwGeneralMaxStages-1 && textureUsedInStage[stage2][0] && gci.stages[stage2].dwTexture != (unsigned int)tex2 )
746
{
747
StageOperate &op = ((StageOperate*)(&(gci.stages[stage2].colorOp)))[curN64Stage%2];
748
SkipStage(op, stage2);
749
}
750
751
if( stage1 <= stage2 )
752
{
753
curStage = stage1;
754
return 1;
755
}
756
else
757
{
758
curStage = stage2;
759
return 2;
760
}
761
}
762
}
763
else
764
{
765
return 0;
766
}
767
}
768
769
770
int CGeneralCombiner::CheckWhichTexToUseInThisStage(int curN64Stage, int curStage, GeneralCombinerInfo &gci)
771
{
772
// There are two texels to used, which one I should use in the current DirectX stage?
773
if( curN64Stage%2 )
774
{
775
if( !textureUsedInStage[curStage][0] )
776
return 0;
777
else
778
return gci.stages[curStage].dwTexture;
779
}
780
else
781
{
782
return 0;
783
}
784
}
785
786
/*
787
*
788
*/
789
790
int CGeneralCombiner::ParseDecodedMux()
791
{
792
GeneralCombinerInfo gci;
793
int stages[2];
794
795
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
796
797
GenCI_Init(gci);
798
799
for( int i=0; i<2; i++ )
800
{
801
//i=0 Color Channel
802
//i=1 Alpha Channel
803
804
stages[i] = 0;
805
int n=0; //stage count
806
807
for( int j=0; j<2; j++ )
808
{
809
switch( mux.splitType[i+j*2] )
810
{
811
case CM_FMT_TYPE_NOT_USED:
812
continue;
813
case CM_FMT_TYPE_D: // = D
814
// Alpha channel is using different texture from color channel
815
// and the color channel has already used texture, so alpha
816
// channel can not use different texture for this stage anymore,
817
// alpha channel need to skip a stage
818
n = GenCI_Type_D(j*2+i, n, gci);
819
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
820
break;
821
case CM_FMT_TYPE_A_ADD_D: // = A+D
822
n=GenCI_Type_A_ADD_D(j*2+i, n, gci);
823
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
824
break;
825
case CM_FMT_TYPE_A_MOD_C: // = A*C can mapped to MOD(arg1,arg2)
826
n=GenCI_Type_A_MOD_C(j*2+i, n, gci);
827
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
828
break;
829
case CM_FMT_TYPE_A_SUB_B: // = A-B can mapped to SUB(arg1,arg2)
830
n=GenCI_Type_A_SUB_B(j*2+i, n, gci);
831
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
832
break;
833
case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D can mapped to MULTIPLYADD(arg1,arg2,arg0)
834
n=GenCI_Type_A_MOD_C_ADD_D(j*2+i, n, gci);
835
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
836
break;
837
case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B can mapped to LERP(arg1,arg2,arg0)
838
// or mapped to BLENDALPHA(arg1,arg2) if C is
839
// alpha channel or DIF, TEX, FAC, CUR
840
n=GenCI_Type_A_LERP_B_C(j*2+i, n, gci);
841
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
842
break;
843
case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+C can not map very well in 1 stage
844
n=GenCI_Type_A_SUB_B_ADD_D(j*2+i, n, gci);
845
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
846
break;
847
case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C can not map very well in 1 stage
848
n=GenCI_Type_A_SUB_B_MOD_C(j*2+i, n, gci);
849
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
850
break;
851
case CM_FMT_TYPE_A_ADD_B_MOD_C:
852
n=GenCI_Type_A_ADD_B_MOD_C(j*2+i, n, gci);
853
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
854
break;
855
case CM_FMT_TYPE_A_B_C_A:
856
n=GenCI_Type_A_B_C_A(j*2+i, n, gci);
857
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
858
break;
859
case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D can not map very well in 1 stage
860
n=GenCI_Type_A_B_C_D(j*2+i, n, gci);
861
if( j==0 && mux.splitType[i+2] != CM_FMT_TYPE_NOT_USED ) NextStage(n); else n++;
862
break;
863
default:
864
break;
865
}
866
}
867
stages[i] = n;
868
}
869
870
gci.nStages = max(stages[0], stages[1]);
871
if( gci.nStages > m_dwGeneralMaxStages )
872
{
873
resultIsGood = false;
874
gci.nStages = m_dwGeneralMaxStages;
875
}
876
877
if( mux.m_ColorTextureFlag[0] != 0 || mux.m_ColorTextureFlag[1] != 0 )
878
{
879
resultIsGood = false;
880
}
881
882
// The bResultIsGoodWithinStages is for Semi-Pixel shader combiner, don't move the code down
883
gci.bResultIsGoodWithinStages = resultIsGood;
884
if( mux.HowManyConstFactors() > 1 || gci.specularPostOp != MUX_0 || gci.blendingFunc != ENABLE_BOTH )
885
{
886
gci.bResultIsGoodWithinStages = false;
887
}
888
889
if( gci.nStages > stages[0] ) // Color has less stages
890
{
891
for( int i=stages[0]; i<gci.nStages; i++ )
892
{
893
gci.stages[i].colorOp.op = CM_REPLACE;
894
gci.stages[i].colorOp.Arg1 = MUX_COMBINED;
895
gci.stages[i].colorOp.Arg2 = CM_IGNORE;
896
gci.stages[i].colorOp.Arg0 = CM_IGNORE;
897
}
898
}
899
900
if( gci.nStages > stages[1] ) // Color has less stages
901
{
902
for( int i=stages[1]; i<gci.nStages; i++ )
903
{
904
gci.stages[i].alphaOp.op = CM_REPLACE;
905
gci.stages[i].alphaOp.Arg1 = MUX_COMBINED;
906
gci.stages[i].alphaOp.Arg2 = CM_IGNORE;
907
gci.stages[i].alphaOp.Arg0 = CM_IGNORE;
908
}
909
}
910
911
for( int i=0;i<gci.nStages;i++)
912
{
913
gci.stages[i].bTextureUsed = IsTextureUsedInStage(gci.stages[i]);
914
}
915
916
if( !resultIsGood && gci.nStages >= m_dwGeneralMaxStages )
917
{
918
extern int noOfTwoStages;
919
extern GeneralCombinerInfo twostages[];
920
921
for( int k=0; k<noOfTwoStages; k++ )
922
{
923
GeneralCombinerInfo &info = twostages[k];
924
if( (mux.m_dwMux0 == info.dwMux0 && mux.m_dwMux1 == info.dwMux1) ||
925
(info.dwMux0+info.dwMux1 == 0 && info.muxDWords[0] == mux.m_dWords[0] &&
926
info.muxDWords[1] == mux.m_dWords[1] && info.muxDWords[2] == mux.m_dWords[2] &&
927
info.muxDWords[3] == mux.m_dWords[3] && info.m_dwShadeAlphaChannelFlag == mux.m_dwShadeAlphaChannelFlag &&
928
info.m_dwShadeColorChannelFlag == mux.m_dwShadeColorChannelFlag ) )
929
{
930
memcpy(&gci, &info, sizeof(GeneralCombinerInfo) );
931
resultIsGood = true;
932
break;
933
}
934
}
935
}
936
937
#ifdef DEBUGGER
938
if( !resultIsGood )
939
{
940
DecodedMux &mux = *(*m_ppGeneralDecodedMux);
941
// Generated combiner mode is not good enough within the limited stages
942
DebuggerAppendMsg("\n/*");
943
mux.DisplayMuxString("Overflowed");
944
mux.DisplaySimpliedMuxString("Overflowed");
945
DebuggerAppendMsg("Generated combiners:");
946
General_DisplayBlendingStageInfo(gci);
947
DebuggerAppendMsg("*/\n");
948
DebuggerAppendMsg("\n\n");
949
DebuggerAppendMsg("{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",
950
mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);
951
DebuggerAppendMsg("\t%d,\t// number of stages\n\tENABLE_BOTH,\n\t0,\t\t// Constant color\n\t0x%08X, 0x%08X, 0,\t// Shade and specular color flags\n\t0x%08X, 0x%08X,\t// constant color texture flags\n",
952
2,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);
953
DebuggerAppendMsg("\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");
954
DebuggerAppendMsg("\t\t{MOD(T0,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");
955
}
956
#else
957
if( !resultIsGood )
958
{
959
FILE *fp=NULL;
960
fp = fopen("C:\\rice\\RiceVideoMUX.log","a");
961
if( fp )
962
{
963
fprintf(fp,"\n/*\n");
964
mux.LogMuxString("Overflowed",fp);
965
fprintf(fp,"\n\n");
966
mux.LogSimpliedMuxString("Overflowed",fp);
967
fprintf(fp,"Generated combiners:");
968
//General_DisplayBlendingStageInfo(gci);
969
fprintf(fp,"\n*/\n");
970
fprintf(fp,"\n");
971
fprintf(fp,"{\n\t0x%08X, 0x%08X, 0x%08X, 0x%08X,\t// Simplified mux\n\t0x%08X, 0x%08X,\t\t// 64bit Mux\n",
972
mux.m_dWords[0],mux.m_dWords[1],mux.m_dWords[2],mux.m_dWords[3],mux.m_dwMux0,mux.m_dwMux1);
973
fprintf(fp,"\t%d,\t// number of stages\n\tENABLE_BOTH,\n\tMUX_ENV,\t\t// Constant color\n\t0x%08X, 0x%08X, 0,\t// Shade and specular color flags\n\t0x%08X, 0x%08X,\t// constant color texture flags\n",
974
2,mux.m_dwShadeColorChannelFlag, mux.m_dwShadeAlphaChannelFlag,mux.m_ColorTextureFlag[0],mux.m_ColorTextureFlag[1]);
975
fprintf(fp,"\t{\n\t\t{MOD(T0,DIF), MOD(T0,DIF), 0, true}, // Stage 0\n");
976
fprintf(fp,"\t\t{LERP(T1,CUR,DIF), SKIP, 1, true}, // Stage 1\n\t}\n},");
977
978
fclose(fp);
979
}
980
}
981
#endif
982
983
return SaveParserResult(gci);
984
}
985
986
987
bool CGeneralCombiner::IsTextureUsedInStage(GeneralCombineStage &stage)
988
{
989
if( (stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||
990
(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL0 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL0 ||
991
(stage.colorOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.colorOp.Arg0 &MUX_MASK)==MUX_TEXEL1 ||
992
(stage.alphaOp.Arg1&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg2&MUX_MASK)==MUX_TEXEL1 || (stage.alphaOp.Arg0 &MUX_MASK)==MUX_TEXEL1 )
993
{
994
return true;
995
}
996
else
997
return false;
998
}
999
1000
1001
int CGeneralCombiner::SaveParserResult(GeneralCombinerInfo &result)
1002
{
1003
result.muxDWords[0] = (*m_ppGeneralDecodedMux)->m_dWords[0];
1004
result.muxDWords[1] = (*m_ppGeneralDecodedMux)->m_dWords[1];
1005
result.muxDWords[2] = (*m_ppGeneralDecodedMux)->m_dWords[2];
1006
result.muxDWords[3] = (*m_ppGeneralDecodedMux)->m_dWords[3];
1007
result.m_dwShadeAlphaChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeAlphaChannelFlag;
1008
result.m_dwShadeColorChannelFlag = (*m_ppGeneralDecodedMux)->m_dwShadeColorChannelFlag;
1009
result.colorTextureFlag[0] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[0];
1010
result.colorTextureFlag[1] = (*m_ppGeneralDecodedMux)->m_ColorTextureFlag[1];
1011
result.dwMux0 = (*m_ppGeneralDecodedMux)->m_dwMux0;
1012
result.dwMux1 = (*m_ppGeneralDecodedMux)->m_dwMux1;
1013
1014
m_vCompiledCombinerStages.push_back(result);
1015
m_lastGeneralIndex = m_vCompiledCombinerStages.size()-1;
1016
1017
return m_lastGeneralIndex;
1018
}
1019
1020
1021
int CGeneralCombiner::FindCompiledMux( )
1022
{
1023
#ifdef DEBUGGER
1024
if( debuggerDropCombiners || debuggerDropGeneralCombiners )
1025
{
1026
m_vCompiledCombinerStages.clear();
1027
//m_dwLastMux0 = m_dwLastMux1 = 0;
1028
debuggerDropCombiners = false;
1029
debuggerDropGeneralCombiners = false;
1030
}
1031
#endif
1032
1033
for( uint32 i=0; i<m_vCompiledCombinerStages.size(); i++ )
1034
{
1035
if( m_vCompiledCombinerStages[i].dwMux0 == (*m_ppGeneralDecodedMux)->m_dwMux0 && m_vCompiledCombinerStages[i].dwMux1 == (*m_ppGeneralDecodedMux)->m_dwMux1 )
1036
{
1037
m_lastGeneralIndex = i;
1038
return i;
1039
}
1040
}
1041
1042
return -1;
1043
}
1044
1045
1046
1047
bool LM_textureUsedInStage[8];
1048
void CGeneralCombiner::LM_GenCI_Init(GeneralCombinerInfo &gci)
1049
{
1050
gci.specularPostOp=gci.TFactor=MUX_0;
1051
1052
gci.blendingFunc = ENABLE_BOTH;
1053
1054
for( int i=0; i<8; i++)
1055
{
1056
gci.stages[i].dwTexture = 0;
1057
LM_textureUsedInStage[i] = false;
1058
}
1059
}
1060
1061
1062
//#define fillstage(opr,a1,a2,a3) {op->op=opr;op->Arg1=a1;op->Arg2=a2;op->Arg0=a3;curStage++;}
1063
inline void FillStage(StageOperate &op, uint32 opr, uint32 a1, uint32 a2, uint32 a3)
1064
{
1065
op.op = opr;
1066
op.Arg1 = a1;
1067
op.Arg2 = a2;
1068
op.Arg0 = a3;
1069
}
1070
1071
/************************************************************************/
1072
/* New functions, will generate stages within stage limited */
1073
/* and return the number of stages used. */
1074
/************************************************************************/
1075
int CGeneralCombiner::LM_GenCI_Type_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1076
{
1077
int originalstage=curStage;
1078
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage]))) + channel;
1079
if( checktexture && LM_Check1TxtrForAlpha(curStage, gci, m.d ) )
1080
{
1081
if( limit > 1 )
1082
{
1083
FillStage(*op,CM_REPLACE,MUX_COMBINED,CM_IGNORE,CM_IGNORE);
1084
curStage++;
1085
op = ((StageOperate*)(&(gci.stages[curStage]))) + channel;
1086
FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE);
1087
}
1088
else
1089
{
1090
// It is not allowed to use two stages, what to do?
1091
// It should not happen anyway
1092
TRACE0("Check me here, at LM_GenCI_Type_D");
1093
}
1094
}
1095
else
1096
{
1097
FillStage(*op,CM_REPLACE,m.d,CM_IGNORE,CM_IGNORE);
1098
}
1099
1100
gci.stages[curStage].dwTexture = GetTexelNumber(m);
1101
LM_textureUsedInStage[curStage] = IsTxtrUsed(m);
1102
curStage++;
1103
1104
return curStage-originalstage;
1105
}
1106
int CGeneralCombiner::LM_GenCI_Type_A_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci, uint32 dxop)
1107
{
1108
int originalstage=curStage;
1109
StageOperate *op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1110
1111
int numberOfTex = CountTexel1Cycle(m);
1112
1113
if( numberOfTex == 2 )
1114
{
1115
// As we can not use both texture in one stage
1116
// we split them to two stages
1117
// Stage1: SELECT txt1
1118
// Stage2: MOD txt2
1119
1120
if( checktexture )
1121
{
1122
if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) )
1123
{
1124
FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);
1125
gci.stages[curStage].dwTexture = toTex(m.c);
1126
LM_textureUsedInStage[curStage] = true;
1127
curStage++;
1128
1129
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1130
FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);
1131
gci.stages[curStage].dwTexture = toTex(m.a);
1132
LM_textureUsedInStage[curStage] = true;
1133
curStage++;
1134
}
1135
else
1136
{
1137
FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);
1138
gci.stages[curStage].dwTexture = toTex(m.a);
1139
LM_textureUsedInStage[curStage] = true;
1140
curStage++;
1141
1142
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1143
FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);
1144
gci.stages[curStage].dwTexture = toTex(m.c);
1145
LM_textureUsedInStage[curStage] = true;
1146
curStage++;
1147
}
1148
}
1149
else
1150
{
1151
FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);
1152
gci.stages[curStage].dwTexture = toTex(m.a);
1153
LM_textureUsedInStage[curStage] = true;
1154
curStage++;
1155
1156
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1157
FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);
1158
gci.stages[curStage].dwTexture = toTex(m.c);
1159
LM_textureUsedInStage[curStage] = true;
1160
curStage++;
1161
}
1162
}
1163
else if( numberOfTex == 1)
1164
{
1165
if( checktexture )
1166
{
1167
if( isTex(m.a) )
1168
{
1169
if( LM_Check1TxtrForAlpha(curStage, gci, m.a ) )
1170
{
1171
FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);
1172
curStage++;
1173
1174
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1175
FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);
1176
gci.stages[curStage].dwTexture = toTex(m.a);
1177
LM_textureUsedInStage[curStage] = true;
1178
curStage++;
1179
}
1180
else
1181
{
1182
FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);
1183
gci.stages[curStage].dwTexture = toTex(m.a);
1184
LM_textureUsedInStage[curStage] = true;
1185
curStage++;
1186
1187
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1188
FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);
1189
curStage++;
1190
}
1191
}
1192
else
1193
{
1194
if( LM_Check1TxtrForAlpha(curStage, gci, m.c ) )
1195
{
1196
FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);
1197
curStage++;
1198
1199
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1200
FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);
1201
gci.stages[curStage].dwTexture = toTex(m.c);
1202
LM_textureUsedInStage[curStage] = true;
1203
curStage++;
1204
}
1205
else
1206
{
1207
FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);
1208
gci.stages[curStage].dwTexture = toTex(m.c);
1209
LM_textureUsedInStage[curStage] = true;
1210
curStage++;
1211
1212
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1213
FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);
1214
curStage++;
1215
}
1216
}
1217
}
1218
else
1219
{
1220
if( isTex(m.a) )
1221
{
1222
FillStage(*op,CM_REPLACE,m.a,CM_IGNORE,CM_IGNORE);
1223
gci.stages[curStage].dwTexture = toTex(m.a);
1224
LM_textureUsedInStage[curStage] = true;
1225
curStage++;
1226
1227
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1228
FillStage(*op,dxop,m.c,MUX_COMBINED,CM_IGNORE);
1229
curStage++;
1230
}
1231
else
1232
{
1233
FillStage(*op,CM_REPLACE,m.c,CM_IGNORE,CM_IGNORE);
1234
gci.stages[curStage].dwTexture = toTex(m.c);
1235
LM_textureUsedInStage[curStage] = true;
1236
curStage++;
1237
1238
op = ((StageOperate*)(&(gci.stages[curStage].colorOp))) + channel;
1239
FillStage(*op,dxop,m.a,MUX_COMBINED,CM_IGNORE);
1240
curStage++;
1241
}
1242
1243
}
1244
}
1245
else
1246
{
1247
FillStage(*op,dxop,m.a,m.c,CM_IGNORE);
1248
curStage++;
1249
}
1250
1251
return curStage-originalstage;
1252
}
1253
int CGeneralCombiner::LM_GenCI_Type_A_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1254
{
1255
return 0;
1256
}
1257
int CGeneralCombiner::LM_GenCI_Type_A_SUB_B(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1258
{
1259
return 0;
1260
}
1261
int CGeneralCombiner::LM_GenCI_Type_A_LERP_B_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1262
{
1263
return 0;
1264
}
1265
int CGeneralCombiner::LM_GenCI_Type_A_MOD_C_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1266
{
1267
return 0;
1268
}
1269
int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1270
{
1271
return 0;
1272
}
1273
int CGeneralCombiner::LM_GenCI_Type_A_SUB_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1274
{
1275
return 0;
1276
}
1277
int CGeneralCombiner::LM_GenCI_Type_A_ADD_B_MOD_C(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1278
{
1279
return 0;
1280
}
1281
int CGeneralCombiner::LM_GenCI_Type_A_B_C_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1282
{
1283
return 0;
1284
}
1285
int CGeneralCombiner::LM_GenCI_Type_A_B_C_A(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1286
{
1287
return 0;
1288
}
1289
1290
int CGeneralCombiner::LM_ParseDecodedMux()
1291
{
1292
return 0;
1293
}
1294
1295
bool CGeneralCombiner::LM_Check1TxtrForAlpha(int curStage, GeneralCombinerInfo &gci, uint32 val )
1296
{
1297
return !( isTex(val) && LM_textureUsedInStage[curStage] && gci.stages[curStage].dwTexture != (unsigned int)toTex(val) );
1298
}
1299
1300
1301
void CGeneralCombiner::LM_SkipStage(StageOperate &op)
1302
{
1303
op.op = CM_REPLACE;
1304
op.Arg1 = MUX_COMBINED;
1305
op.Arg2 = CM_IGNORE;
1306
op.Arg0 = CM_IGNORE;
1307
}
1308
1309
1310