2 Copyright (C) 2003 Rice1964
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.
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.
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.
21 const char * sc_szBlClr[4] = { "In", "Mem", "Bl", "Fog" };
22 const char * sc_szBlA1[4] = { "AIn", "AFog", "AShade", "0" };
23 const char * sc_szBlA2[4] = { "1-A", "AMem", "1", "0" };
25 //========================================================================
26 void CBlender::InitBlenderMode(void) // Set Alpha Blender mode
28 //1. Z_COMPARE -- Enable / Disable Zbuffer compare
30 // 0 - Disable ZBuffer
32 //2. Z_UPDATE -- Enable / Disable Zbuffer update
33 // 1 - Enable ZBuffer writeable
34 // 0 - Zbuffer not writeable
36 //3. AA_EN and IM_RD -- Anti-Alias
37 // AA_EN - Enable anti-aliase
38 // AA_EN | IM_RD - Reduced anti-aliase
40 // - - Disable anti-aliase
43 // #define ZMODE_OPA 0 -- Usually used with Z_COMPARE and Z_UPDATE
44 // or used without neither Z_COMPARE or Z_UPDATE
45 // if used with Z_COMPARE and Z_UPDATE, then this is
46 // the regular ZBuffer mode, with compare and update
47 // #define ZMODE_INTER 0x400
48 // #define ZMODE_XLU 0x800 -- Usually used with Z_COMPARE, but not with Z_UPDATE
49 // Do only compare, no zbuffer update.
50 // Not output if the z value is the same
51 // #define ZMODE_DEC 0xc00 -- Usually used with Z_COMPARE, but not with Z_UPDATE
52 // Do only compare, no update, but because this is
53 // decal mode, so image should be updated even
54 // the z value is the same as compared.
56 CRender *render = CRender::g_pRender;
58 // Alpha Blender Modes
61 6. FORCE_BL - Alpha blending at blender stage
62 1 - Enable alpha blending at blender
63 0 - Disable alpha blending at blender
65 Alpha blending at blender is usually used to render XLU surface
66 if enabled, then use the blending setting of C1 and C2
68 7. ALPHA_CVG_SEL - Output full alpha from the color combiner, usually not used together
69 with FORCE_BL. If it is used together with FORCE_BL, then ignore this
71 8. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha
73 9. TEX_EDGE - Ignore this
75 10.CLR_ON_CVG - Used with XLU surfaces, ignore it
78 #define CVG_DST_CLAMP 0 - Usually used with OPA surface
79 #define CVG_DST_WRAP 0x100 - Usually used with XLU surface or OPA line
80 #define CVG_DST_FULL 0x200 - ?
81 #define CVG_DST_SAVE 0x300 - ?
84 Possible Blending Inputs:
86 In - Input from color combiner
87 Mem - Input from current frame buffer
91 Possible Blending Factors:
92 A-IN - Alpha from color combiner
93 A-MEM - Alpha from current frame buffer
95 A-FOG - Alpha of fog color
96 A-SHADE - Alpha of shade
100 #define BLEND_NOOP 0x0000
102 #define BLEND_NOOP5 0xcc48 // Fog * 0 + Mem * 1
103 #define BLEND_NOOP4 0xcc08 // Fog * 0 + In * 1
104 #define BLEND_FOG_ASHADE 0xc800
105 #define BLEND_FOG_3 0xc000 // Fog * AIn + In * 1-A
106 #define BLEND_FOG_MEM 0xc440 // Fog * AFog + Mem * 1-A
107 #define BLEND_FOG_APRIM 0xc400 // Fog * AFog + In * 1-A
109 #define BLEND_BLENDCOLOR 0x8c88
110 #define BLEND_BI_AFOG 0x8400 // Bl * AFog + In * 1-A
111 #define BLEND_BI_AIN 0x8040 // Bl * AIn + Mem * 1-A
113 #define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?!
114 #define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A
116 #define BLEND_NOOP3 0x0c48 // In * 0 + Mem * 1
117 #define BLEND_PASS 0x0c08 // In * 0 + In * 1
118 #define BLEND_FOG_MEM_IN_MEM 0x0440 // In * AFog + Mem * 1-A
119 #define BLEND_FOG_MEM_FOG_MEM 0x04c0 // In * AFog + Fog * 1-A
120 #define BLEND_OPA 0x0044 // In * AIn + Mem * AMem
121 #define BLEND_XLU 0x0040
122 #define BLEND_MEM_ALPHA_IN 0x4044 // Mem * AIn + Mem * AMem
125 uint32 blendmode_1 = (uint32)( gRDP.otherMode.blender & 0xcccc );
126 uint32 blendmode_2 = (uint32)( gRDP.otherMode.blender & 0x3333 );
127 uint32 cycletype = gRDP.otherMode.cycle_type;
131 case CYCLE_TYPE_FILL:
132 //BlendFunc(BLEND_ONE, BLEND_ZERO);
136 case CYCLE_TYPE_COPY:
138 BlendFunc(BLEND_ONE, BLEND_ZERO);
142 if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp )
144 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
150 if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 )
152 BlendFunc(BLEND_ONE, BLEND_ZERO);
158 switch( blendmode_1+blendmode_2 )
160 case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1
161 case BLEND_FOG_APRIM+(BLEND_PASS>>2):
162 BlendFunc(BLEND_ONE, BLEND_ZERO);
163 if( gRDP.otherMode.alpha_cvg_sel )
172 render->SetAlphaTestEnable( ((gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3)==1 ? TRUE : FALSE);
174 case BLEND_PASS+(BLEND_OPA>>2):
176 // Cycle1: In * 0 + In * 1
177 // Cycle2: In * AIn + Mem * AMem
178 if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel )
180 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
185 BlendFunc(BLEND_ONE, BLEND_ZERO);
189 case BLEND_PASS + (BLEND_XLU>>2):
191 // Cycle1: In * 0 + In * 1
192 // Cycle2: In * AIn + Mem * 1-A
193 case BLEND_FOG_ASHADE + (BLEND_XLU>>2):
194 //Cycle1: Fog * AShade + In * 1-A
195 //Cycle2: In * AIn + Mem * 1-A
196 case BLEND_FOG_APRIM + (BLEND_XLU>>2):
197 //Cycle1: Fog * AFog + In * 1-A
198 //Cycle2: In * AIn + Mem * 1-A
199 //case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
200 //Cycle1: In * AFog + Fog * 1-A
201 //Cycle2: In * AIn + Mem * AMem
202 case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):
203 //Cycle1: In * AFog + Fog * 1-A
204 //Cycle2: In * 0 + In * 1
205 case BLEND_XLU + (BLEND_XLU>>2):
206 //Cycle1: Fog * AFog + In * 1-A
207 //Cycle2: In * AIn + Mem * 1-A
208 case BLEND_BI_AFOG + (BLEND_XLU>>2):
209 //Cycle1: Bl * AFog + In * 1-A
210 //Cycle2: In * AIn + Mem * 1-A
211 case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):
212 //Cycle1: In * AIn + Mem * 1-A
213 //Cycle2: In * AFog + Mem * 1-A
214 case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):
215 //Cycle1: In * 0 + In * 1
216 //Cycle2: In * AFog + Mem * 1-A
217 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
220 case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
221 //Cycle1: In * AFog + Fog * 1-A
222 //Cycle2: In * AIn + Mem * AMem
223 BlendFunc(BLEND_ONE, BLEND_ZERO);
227 case BLEND_FOG_APRIM + (BLEND_OPA>>2):
229 //Cycle1: Fog * AFog + In * 1-A
230 //Cycle2: In * AIn + Mem * AMem
231 case BLEND_FOG_ASHADE + (BLEND_OPA>>2):
232 //Cycle1: Fog * AShade + In * 1-A
233 //Cycle2: In * AIn + Mem * AMem
234 case BLEND_BI_AFOG + (BLEND_OPA>>2):
235 //Cycle1: Bl * AFog + In * 1-A
236 //Cycle2: In * AIn + Mem * 1-AMem
237 case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):
238 //Cycle1: Fog * AShade + In * 1-A
239 //Cycle2: In * AIn + In * 1-A
240 case BLEND_NOOP + (BLEND_OPA>>2):
241 //Cycle1: In * AIn + In * 1-A
242 //Cycle2: In * AIn + Mem * AMem
243 case BLEND_NOOP4 + (BLEND_NOOP>>2):
244 //Cycle1: Fog * AIn + In * 1-A
245 //Cycle2: In * 0 + In * 1
246 case BLEND_FOG_ASHADE+(BLEND_PASS>>2):
247 //Cycle1: Fog * AShade + In * 1-A
248 //Cycle2: In * 0 + In * 1
249 case BLEND_FOG_3+(BLEND_PASS>>2):
250 BlendFunc(BLEND_ONE, BLEND_ZERO);
253 case BLEND_FOG_ASHADE+0x0301:
254 // c800 - Cycle1: Fog * AShade + In * 1-A
255 // 0301 - Cycle2: In * 0 + In * AMem
256 BlendFunc(BLEND_SRCALPHA, BLEND_ZERO);
260 // 0c08 - Cycle1: In * 0 + In * 1
261 // 1111 - Cycle2: Mem * AFog + Mem * AMem
262 BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);
269 uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;
270 uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;
271 uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;
272 uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;
274 uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;
275 uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;
276 uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;
277 uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;
279 TRACE0("Unknown Blender Mode: 2 cycle");
280 DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t%04x - Cycle2:\t%s * %s + %s * %s", blendmode_1,
281 sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1], blendmode_2,
282 sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);
286 if( blendmode_2 == (BLEND_PASS>>2) )
288 BlendFunc(BLEND_ONE, BLEND_ZERO);
292 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
298 default: // 1/2 Cycle or Copy
299 if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp && blendmode_1 != BLEND_FOG_ASHADE )
301 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
305 if( gRDP.otherMode.force_bl && options.enableHackForGames == HACK_FOR_COMMANDCONQUER )
307 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
313 //if( (blendmode_1>>2) != blendmode_2 )
315 // DebuggerAppendMsg("Warning: in 1 cycle mode, blend1!=blend2");
319 switch ( blendmode_1 )
320 //switch ( blendmode_2<<2 )
322 case BLEND_XLU: // IN * A_IN + MEM * (1-A_IN)
323 case BLEND_BI_AIN: // Bl * AIn + Mem * 1-A
324 case BLEND_FOG_MEM: // c440 - Cycle1: Fog * AFog + Mem * 1-A
325 case BLEND_FOG_MEM_IN_MEM: // c440 - Cycle1: In * AFog + Mem * 1-A
326 case BLEND_BLENDCOLOR: //Bl * 0 + Bl * 1
327 case 0x00c0: //In * AIn + Fog * 1-A
328 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
331 case BLEND_MEM_ALPHA_IN: // Mem * AIn + Mem * AMem
332 BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);
335 case BLEND_PASS: // IN * 0 + IN * 1
336 BlendFunc(BLEND_ONE, BLEND_ZERO);
337 if( gRDP.otherMode.alpha_cvg_sel )
346 case BLEND_OPA: // IN * A_IN + MEM * A_MEM
347 if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
349 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
353 BlendFunc(BLEND_ONE, BLEND_ZERO);
357 case BLEND_NOOP: // IN * A_IN + IN * (1 - A_IN)
358 case BLEND_FOG_ASHADE: // Fog * AShade + In * 1-A
359 case BLEND_FOG_MEM_3: // Mem * AFog + Fog * 1-A
360 case BLEND_BI_AFOG: // Bl * AFog + In * 1-A
361 BlendFunc(BLEND_ONE, BLEND_ZERO);
364 case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A
365 BlendFunc(BLEND_INVSRCALPHA, BLEND_ZERO);
368 case BLEND_NOOP3: // In * 0 + Mem * 1
369 case BLEND_NOOP5: // Fog * 0 + Mem * 1
370 BlendFunc(BLEND_ZERO, BLEND_ONE);
373 case BLEND_MEM: // Mem * 0 + Mem * 1-A
375 BlendFunc(BLEND_ZERO, BLEND_ONE);
382 uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;
383 uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;
384 uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;
385 uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;
387 uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;
388 uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;
389 uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;
390 uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;
392 TRACE0("Unknown Blender Mode: 1 cycle");
393 DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t\tCycle2:\t%s * %s + %s * %s", blendmode_1,
394 sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1],
395 sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);
398 BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
400 render->SetAlphaTestEnable(TRUE);