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 "Render.h" |
20 | |
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" }; |
24 | |
25 | //======================================================================== |
26 | void CBlender::InitBlenderMode(void) // Set Alpha Blender mode |
27 | { |
28 | //1. Z_COMPARE -- Enable / Disable Zbuffer compare |
29 | // 1 - Enable ZBuffer |
30 | // 0 - Disable ZBuffer |
31 | |
32 | //2. Z_UPDATE -- Enable / Disable Zbuffer update |
33 | // 1 - Enable ZBuffer writeable |
34 | // 0 - Zbuffer not writeable |
35 | |
36 | //3. AA_EN and IM_RD -- Anti-Alias |
37 | // AA_EN - Enable anti-aliase |
38 | // AA_EN | IM_RD - Reduced anti-aliase |
39 | // IM_RD - ?? |
40 | // - - Disable anti-aliase |
41 | |
42 | //4. ZMode |
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. |
55 | |
56 | CRender *render = CRender::g_pRender; |
57 | |
58 | // Alpha Blender Modes |
59 | |
60 | /* |
61 | 6. FORCE_BL - Alpha blending at blender stage |
62 | 1 - Enable alpha blending at blender |
63 | 0 - Disable alpha blending at blender |
64 | |
65 | Alpha blending at blender is usually used to render XLU surface |
66 | if enabled, then use the blending setting of C1 and C2 |
67 | |
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 |
70 | |
71 | 8. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha |
72 | |
73 | 9. TEX_EDGE - Ignore this |
74 | |
75 | 10.CLR_ON_CVG - Used with XLU surfaces, ignore it |
76 | |
77 | 11.CVG_DST |
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 - ? |
82 | |
83 | |
84 | Possible Blending Inputs: |
85 | |
86 | In - Input from color combiner |
87 | Mem - Input from current frame buffer |
88 | Fog - Fog generator |
89 | BL - Blender |
90 | |
91 | Possible Blending Factors: |
92 | A-IN - Alpha from color combiner |
93 | A-MEM - Alpha from current frame buffer |
94 | (1-A) - |
95 | A-FOG - Alpha of fog color |
96 | A-SHADE - Alpha of shade |
97 | 1 - 1 |
98 | 0 - 0 |
99 | */ |
100 | #define BLEND_NOOP 0x0000 |
101 | |
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 |
108 | |
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 |
112 | |
113 | #define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?! |
114 | #define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A |
115 | |
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 |
123 | |
124 | |
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; |
128 | |
129 | switch( cycletype ) |
130 | { |
131 | case CYCLE_TYPE_FILL: |
132 | //BlendFunc(BLEND_ONE, BLEND_ZERO); |
133 | //Enable(); |
134 | Disable(); |
135 | break; |
136 | case CYCLE_TYPE_COPY: |
137 | //Disable(); |
138 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
139 | Enable(); |
140 | break; |
141 | case CYCLE_TYPE_2: |
142 | if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp ) |
143 | { |
144 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
145 | Enable(); |
146 | break; |
147 | } |
148 | |
149 | /* |
150 | if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 ) |
151 | { |
152 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
153 | Enable(); |
154 | break; |
155 | } |
156 | */ |
157 | |
158 | switch( blendmode_1+blendmode_2 ) |
159 | { |
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 ) |
164 | { |
165 | Enable(); |
166 | } |
167 | else |
168 | { |
169 | Disable(); |
170 | } |
171 | |
172 | render->SetAlphaTestEnable( ((gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3)==1 ? TRUE : FALSE); |
173 | break; |
174 | case BLEND_PASS+(BLEND_OPA>>2): |
175 | // 0x0c19 |
176 | // Cycle1: In * 0 + In * 1 |
177 | // Cycle2: In * AIn + Mem * AMem |
178 | if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel ) |
179 | { |
180 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
181 | Enable(); |
182 | } |
183 | else |
184 | { |
185 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
186 | Enable(); |
187 | } |
188 | break; |
189 | case BLEND_PASS + (BLEND_XLU>>2): |
190 | // 0x0c18 |
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); |
218 | Enable(); |
219 | break; |
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); |
224 | Enable(); |
225 | break; |
226 | |
227 | case BLEND_FOG_APRIM + (BLEND_OPA>>2): |
228 | // For Golden Eye |
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); |
251 | Enable(); |
252 | break; |
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); |
257 | Enable(); |
258 | break; |
259 | case 0x0c08+0x1111: |
260 | // 0c08 - Cycle1: In * 0 + In * 1 |
261 | // 1111 - Cycle2: Mem * AFog + Mem * AMem |
262 | BlendFunc(BLEND_ZERO, BLEND_DESTALPHA); |
263 | Enable(); |
264 | break; |
265 | default: |
266 | #ifdef DEBUGGER |
267 | if( pauseAtNext ) |
268 | { |
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; |
273 | |
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; |
278 | |
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]); |
283 | |
284 | } |
285 | #endif |
286 | if( blendmode_2 == (BLEND_PASS>>2) ) |
287 | { |
288 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
289 | } |
290 | else |
291 | { |
292 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
293 | } |
294 | Enable(); |
295 | break; |
296 | } |
297 | break; |
298 | default: // 1/2 Cycle or Copy |
299 | if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp && blendmode_1 != BLEND_FOG_ASHADE ) |
300 | { |
301 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
302 | Enable(); |
303 | break; |
304 | } |
305 | if( gRDP.otherMode.force_bl && options.enableHackForGames == HACK_FOR_COMMANDCONQUER ) |
306 | { |
307 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
308 | Enable(); |
309 | break; |
310 | } |
311 | |
312 | #ifdef DEBUGGER |
313 | //if( (blendmode_1>>2) != blendmode_2 ) |
314 | //{ |
315 | // DebuggerAppendMsg("Warning: in 1 cycle mode, blend1!=blend2"); |
316 | //} |
317 | #endif |
318 | |
319 | switch ( blendmode_1 ) |
320 | //switch ( blendmode_2<<2 ) |
321 | { |
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); |
329 | Enable(); |
330 | break; |
331 | case BLEND_MEM_ALPHA_IN: // Mem * AIn + Mem * AMem |
332 | BlendFunc(BLEND_ZERO, BLEND_DESTALPHA); |
333 | Enable(); |
334 | break; |
335 | case BLEND_PASS: // IN * 0 + IN * 1 |
336 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
337 | if( gRDP.otherMode.alpha_cvg_sel ) |
338 | { |
339 | Enable(); |
340 | } |
341 | else |
342 | { |
343 | Disable(); |
344 | } |
345 | break; |
346 | case BLEND_OPA: // IN * A_IN + MEM * A_MEM |
347 | if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS ) |
348 | { |
349 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
350 | } |
351 | else |
352 | { |
353 | BlendFunc(BLEND_ONE, BLEND_ZERO); |
354 | } |
355 | Enable(); |
356 | break; |
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); |
362 | Enable(); |
363 | break; |
364 | case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A |
365 | BlendFunc(BLEND_INVSRCALPHA, BLEND_ZERO); |
366 | Enable(); |
367 | break; |
368 | case BLEND_NOOP3: // In * 0 + Mem * 1 |
369 | case BLEND_NOOP5: // Fog * 0 + Mem * 1 |
370 | BlendFunc(BLEND_ZERO, BLEND_ONE); |
371 | Enable(); |
372 | break; |
373 | case BLEND_MEM: // Mem * 0 + Mem * 1-A |
374 | // WaveRace |
375 | BlendFunc(BLEND_ZERO, BLEND_ONE); |
376 | Enable(); |
377 | break; |
378 | default: |
379 | #ifdef DEBUGGER |
380 | if( pauseAtNext ) |
381 | { |
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; |
386 | |
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; |
391 | |
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]); |
396 | } |
397 | #endif |
398 | BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA); |
399 | Enable(); |
400 | render->SetAlphaTestEnable(TRUE); |
401 | break; |
402 | } |
403 | } |
404 | } |
405 | |