~ubuntu-branches/ubuntu/saucy/mupen64plus-video-rice/saucy

« back to all changes in this revision

Viewing changes to src/Combiner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sven Eckelmann
  • Date: 2011-01-22 11:05:28 UTC
  • Revision ID: james.westby@ubuntu.com-20110122110528-k6z84gdespqqd9zp
Tags: upstream-1.99.4
ImportĀ upstreamĀ versionĀ 1.99.4

Show diffs side-by-side

added added

removed removed

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