/* Copyright (C) 2003 Rice1964 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "stdafx.h" const char * sc_szBlClr[4] = { "In", "Mem", "Bl", "Fog" }; const char * sc_szBlA1[4] = { "AIn", "AFog", "AShade", "0" }; const char * sc_szBlA2[4] = { "1-A", "AMem", "1", "0" }; //======================================================================== void CBlender::InitBlenderMode(void) // Set Alpha Blender mode { //1. Z_CMP -- Enable / Disable Zbuffer compare, SetRenderState( D3DRS_ZENABLE ) // 1 - Enable ZBuffer // 0 - Disable ZBuffer //2. Z_UPD -- Enable / Disable Zbuffer update, SetRenderState( D3DRS_ZWRITEENABLE ) // 1 - Enable ZBuffer writeable // 0 - Zbuffer not writeable //3. AA_EN and IM_RD -- Anti-Alias // AA_EN - Enable anti-aliase // AA_EN | IM_RD - Reduced anti-aliase // IM_RD - ?? // - - Disable anti-aliase //4. ZMode // #define ZMODE_OPA 0 -- Usually used with Z_CMP and Z_UPD // or used without neither Z_CMP or Z_UPD // if used with Z_CMP and Z_UPD, then this is // the regular ZBuffer mode, with compare and update // #define ZMODE_INTER 0x400 // #define ZMODE_XLU 0x800 -- Usually used with Z_CMP, but not with Z_UPD // Do only compare, no zbuffer update. // Not output if the z value is the same // #define ZMODE_DEC 0xc00 -- Usually used with Z_CMP, but not with Z_UPD // Do only compare, no update, but because this is // decal mode, so image should be updated even // the z value is the same as compared. CDaedalusRender *render = CDaedalusRender::g_pRender; // Alpha Blender Modes /* 6. FORCE_BL - Alpha blending at blender stage 1 - Enable alpha blending at blender 0 - Disable alpha blending at blender Alpha blending at blender is usually used to render XLU surface if enabled, then use the blending setting of C1 and C2 7. ALPHA_CVG_SEL - Output full alpha from the color combiner, usually not used together with FORCE_BL. If it is used together with FORCE_BL, then ignore this 8. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha 9. TEX_EDGE - Ignore this 10.CLR_ON_CVG - Used with XLU surfaces, ignore it 11.CVG_DST #define CVG_DST_CLAMP 0 - Usually used with OPA surface #define CVG_DST_WRAP 0x100 - Usually used with XLU surface or OPA line #define CVG_DST_FULL 0x200 - ? #define CVG_DST_SAVE 0x300 - ? Possible Blending Inputs: In - Input from color combiner Mem - Input from current frame buffer Fog - Fog generator BL - Blender Possible Blending Factors: A-IN - Alpha from color combiner A-MEM - Alpha from current frame buffer (1-A) - A-FOG - Alpha of fog color A-SHADE - Alpha of shade 1 - 1 0 - 0 */ #define BLEND_NOOP 0x0000 #define BLEND_NOOP5 0xcc48 // Fog * 0 + Mem * 1 #define BLEND_NOOP4 0xcc08 // Fog * 0 + In * 1 #define BLEND_FOG_ASHADE 0xc800 #define BLEND_FOG_3 0xc000 // Fog * AIn + In * 1-A #define BLEND_FOG_MEM 0xc440 // Fog * AFog + Mem * 1-A #define BLEND_FOG_APRIM 0xc400 // Fog * AFog + In * 1-A #define BLEND_BLENDCOLOR 0x8c88 #define BLEND_BI_AFOG 0x8400 // Bl * AFog + In * 1-A #define BLEND_BI_AIN 0x8040 // Bl * AIn + Mem * 1-A #define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?! #define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A #define BLEND_NOOP3 0x0c48 // In * 0 + Mem * 1 #define BLEND_PASS 0x0c08 // In * 0 + In * 1 #define BLEND_FOG_MEM_IN_MEM 0x0440 // In * AFog + Mem * 1-A #define BLEND_FOG_MEM_FOG_MEM 0x04c0 // In * AFog + Fog * 1-A #define BLEND_OPA 0x0044 // In * AIn + Mem * AMem #define BLEND_XLU 0x0040 u32 blendmode_1 = u32( gRDP.otherMode.blender & 0xcccc ); u32 blendmode_2 = u32( gRDP.otherMode.blender & 0x3333 ); u32 cycletype = gRDP.otherMode.cycle_type; switch( cycletype ) { case CYCTYPE_FILL: //BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); //Enable(); Disable(); break; case CYCTYPE_COPY: //Disable(); BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); Enable(); break; case CYCTYPE_2CYCLE: if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp ) { BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); break; } /* if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 ) { BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); Enable(); break; } */ switch( blendmode_1+blendmode_2 ) { case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1 case BLEND_FOG_APRIM+(BLEND_PASS>>2): BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); if( gRDP.otherMode.alpha_cvg_sel ) { Enable(); } else { Enable(); } break; case BLEND_PASS+(BLEND_OPA>>2): // 0x0c19 // Cycle1: In * 0 + In * 1 // Cycle2: In * AIn + Mem * AMem if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel ) { BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); } else { BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); Enable(); } break; case BLEND_PASS + (BLEND_XLU>>2): // 0x0c18 // Cycle1: In * 0 + In * 1 // Cycle2: In * AIn + Mem * 1-A case BLEND_FOG_ASHADE + (BLEND_XLU>>2): //Cycle1: Fog * AShade + In * 1-A //Cycle2: In * AIn + Mem * 1-A case BLEND_FOG_APRIM + (BLEND_XLU>>2): //Cycle1: Fog * AFog + In * 1-A //Cycle2: In * AIn + Mem * 1-A case BLEND_FOG_APRIM + (BLEND_OPA>>2): //Cycle1: Fog * AFog + In * 1-A //Cycle2: In * AIn + Mem * AMem case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2): //Cycle1: In * AFog + Fog * 1-A //Cycle2: In * AIn + Mem * AMem case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2): //Cycle1: In * AFog + Fog * 1-A //Cycle2: In * 0 + In * 1 case BLEND_XLU + (BLEND_XLU>>2): //Cycle1: Fog * AFog + In * 1-A //Cycle2: In * AIn + Mem * 1-A case BLEND_BI_AFOG + (BLEND_XLU>>2): //Cycle1: Bl * AFog + In * 1-A //Cycle2: In * AIn + Mem * 1-A case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2): //Cycle1: In * AIn + Mem * 1-A //Cycle2: In * AFog + Mem * 1-A case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2): //Cycle1: In * 0 + In * 1 //Cycle2: In * AFog + Mem * 1-A BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); break; case BLEND_FOG_ASHADE + (BLEND_OPA>>2): //Cycle1: Fog * AShade + In * 1-A //Cycle2: In * AIn + Mem * AMem case BLEND_BI_AFOG + (BLEND_OPA>>2): //Cycle1: Bl * AFog + In * 1-A //Cycle2: In * AIn + Mem * 1-AMem case BLEND_FOG_ASHADE + (BLEND_NOOP>>2): //Cycle1: Fog * AShade + In * 1-A //Cycle2: In * AIn + In * 1-A case BLEND_NOOP + (BLEND_OPA>>2): //Cycle1: In * AIn + In * 1-A //Cycle2: In * AIn + Mem * AMem case BLEND_NOOP4 + (BLEND_NOOP>>2): //Cycle1: Fog * AIn + In * 1-A //Cycle2: In * 0 + In * 1 case BLEND_FOG_3+(BLEND_PASS>>2): BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); Enable(); break; default: #ifdef _DEBUG if( pauseAtNext ) { u32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3; u32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3; u32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3; u32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3; u32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3; u32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3; u32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3; u32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3; TRACE0("Unknown Blender Mode: 2 cycle"); DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t%04x - Cycle2:\t%s * %s + %s * %s", blendmode_1, sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1], blendmode_2, sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]); } #endif if( blendmode_2 == (BLEND_PASS>>2) ) { BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); } else { BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); } Enable(); break; } break; default: // 1/2 Cycle or Copy if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp ) { BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); break; } switch ( blendmode_1 ) { case BLEND_XLU: // IN * A_IN + MEM * (1-A_IN) case BLEND_BI_AIN: // Bl * AIn + Mem * 1-A case BLEND_FOG_MEM: // c440 - Cycle1: Fog * AFog + Mem * 1-A case BLEND_FOG_MEM_IN_MEM: // c440 - Cycle1: In * AFog + Mem * 1-A case BLEND_BLENDCOLOR: //Bl * 0 + Bl * 1 BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); break; case BLEND_PASS: // IN * 0 + IN * 1 BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); if( gRDP.otherMode.alpha_cvg_sel ) { Enable(); } else { Disable(); } break; case BLEND_OPA: // IN * A_IN + MEM * A_MEM case BLEND_NOOP: // IN * A_IN + IN * (1 - A_IN) case BLEND_FOG_ASHADE: // Fog * AShade + In * 1-A case BLEND_FOG_MEM_3: // Mem * AFog + Fog * 1-A case BLEND_BI_AFOG: // Bl * AFog + In * 1-A BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO); Enable(); break; case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A BlendFunc(D3DBLEND_INVSRCALPHA, D3DBLEND_ZERO); Enable(); break; case BLEND_NOOP3: // In * 0 + Mem * 1 case BLEND_NOOP5: // Fog * 0 + Mem * 1 BlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE); Enable(); break; case BLEND_MEM: // Mem * 0 + Mem * 1-A // WaveRace BlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE); Enable(); break; default: #ifdef _DEBUG if( pauseAtNext ) { u32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3; u32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3; u32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3; u32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3; u32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3; u32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3; u32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3; u32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3; TRACE0("Unknown Blender Mode: 1 cycle"); DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t\tCycle2:\t%s * %s + %s * %s", blendmode_1, sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1], sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]); } #endif BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); Enable(); render->SetAlphaTestEnable(TRUE); break; } } }