Added missing launcher
[mupen64plus-pandora.git] / source / gles2rice / src / GeneralCombiner.cpp
CommitLineData
292f9317 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*/
18
19#include <algorithm>
20
21#include "GeneralCombiner.h"
22#include "Combiner.h"
23#include "Debugger.h"
24
25extern const int numOf3StageCombiners;
26extern const int numOf2StageCombiners;
27extern GeneralCombinerInfo CombinerTable2Stages[];
28extern GeneralCombinerInfo CombinerTable3Stages[];
29
30CGeneralCombiner::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
48bool isTex(uint32 val)
49{
50 return ( (val&MUX_MASK) == MUX_TEXEL0 || (val&MUX_MASK) == MUX_TEXEL1 );
51}
52int toTex(uint32 val)
53{
54 return (val&MUX_MASK)-MUX_TEXEL0;
55}
56
57bool isComb(uint32 val)
58{
59 return (val&MUX_MASK)==MUX_COMBINED;
60}
61
62#ifdef DEBUGGER
63const char* BlendFuncStr[] = {
64 "Enable both",
65 "Disable alpha",
66 "Disable color",
67 "Disable both",
68 "Color one",
69 "Alpha one",
70};
71const 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
85void 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
119bool textureUsedInStage[8][2];
120bool resultIsGood;
121
122void 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
173int 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
206int 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}
258int 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
268int 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
323int 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
397int 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
506int 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
619int 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
637int 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
654int 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
661int 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
683void 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
692void 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
706void 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
720int 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
770int 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
790int 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
987bool 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
1001int 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
1021int 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
1047bool LM_textureUsedInStage[8];
1048void 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++;}
1063inline 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/************************************************************************/
1075int 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}
1106int 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}
1253int CGeneralCombiner::LM_GenCI_Type_A_ADD_D(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1254{
1255 return 0;
1256}
1257int CGeneralCombiner::LM_GenCI_Type_A_SUB_B(N64CombinerType &m, int curStage, int limit, int channel, bool checktexture, GeneralCombinerInfo &gci)
1258{
1259 return 0;
1260}
1261int 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}
1265int 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}
1269int 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}
1273int 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}
1277int 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}
1281int 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}
1285int 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
1290int CGeneralCombiner::LM_ParseDecodedMux()
1291{
1292 return 0;
1293}
1294
1295bool 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
1301void 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