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