d07c171f |
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 | |