fix some sprite blending cases, regression post 0.9.9. fixes bug #1338

This commit is contained in:
zeromus 2013-10-03 16:52:06 +00:00
parent 927189550a
commit 6b8b766211
1 changed files with 55 additions and 39 deletions

View File

@ -670,44 +670,60 @@ static FORCEINLINE void _master_setFinalOBJColor(GPU *gpu, u8 *dst, u16 color, u
return;
}
if(type == GPU_OBJ_MODE_Transparent || type == GPU_OBJ_MODE_Bitmap)
bool handleTransparentType = type == GPU_OBJ_MODE_Transparent || type == GPU_OBJ_MODE_Bitmap;
if(windowEffectSatisfied)
{
//under these conditions, we always use a normal blend, regardless of BLDCNT specifications.
//no more than one type of blend processing occurs, so this overrides brightness up/down selection.
//NOTE: This is probably happening even outside the effect window, but I'm not sure.
//NOTE: It is unclear whether blend EVA/EVB are affecting this. I don't think so.
u16 backColor = HostReadWord(dst,x<<1);
color = _blend(color,backColor,&gpuBlendTable555[alpha][16-alpha]);
}
else
{
const bool firstTargetSatisfied = gpu->blend1;
const int bg_under = gpu->bgPixels[x];
const bool secondTargetSatisfied = (bg_under != 4) && gpu->blend2[bg_under];
BlendFunc selectedFunc = NoBlend;
//if normal BLDCNT layer target conditions are met, then we can use the BLDCNT-specified color effect
if(FUNC == Blend)
if(handleTransparentType)
{
//blending requires first and second target screens to be satisfied, as well as the window
if(firstTargetSatisfied && secondTargetSatisfied && windowEffectSatisfied) selectedFunc = FUNC;
}
else
{
//brightness up and down requires only the first target screen to be satisfied
if(firstTargetSatisfied && windowEffectSatisfied) selectedFunc = FUNC;
}
switch(selectedFunc)
{
case NoBlend: break;
case Increase: color = gpu->currentFadeInColors[color&0x7FFF]; break;
case Decrease: color = gpu->currentFadeOutColors[color&0x7FFF]; break;
case Blend:
//under these conditions, we always use a normal blend, regardless of BLDCNT specifications.
//no more than one type of blend processing occurs, so this overrides brightness up/down selection.
//NOTE: obj without fine-grained alpha are using EVA/EVB for blending. this is signified by receiving 255 in the alpha
//NOTE: according to nocash.exe, this is affected by the window effects
u16 backColor = HostReadWord(dst,x<<1);
color = gpu->blend(color,backColor);
break;
int eva, evb;
if(alpha == 255)
{
//tested by glory of heracles title screen and "spriteblend" test
eva = gpu->BLDALPHA_EVA;
evb = gpu->BLDALPHA_EVB;
}
else
{
eva = alpha;
evb = 16 - alpha;
}
color = _blend(color,backColor,&gpuBlendTable555[eva][evb]);
}
else
{
const bool firstTargetSatisfied = gpu->blend1;
const int bg_under = gpu->bgPixels[x];
const bool secondTargetSatisfied = (bg_under != 4) && gpu->blend2[bg_under];
BlendFunc selectedFunc = NoBlend;
//if normal BLDCNT layer target conditions are met, then we can use the BLDCNT-specified color effect
if(FUNC == Blend)
{
//blending requires first and second target screens to be satisfied
if(firstTargetSatisfied && secondTargetSatisfied) selectedFunc = FUNC;
}
else
{
//brightness up and down requires only the first target screen to be satisfied
if(firstTargetSatisfied) selectedFunc = FUNC;
}
switch(selectedFunc)
{
case NoBlend: break;
case Increase: color = gpu->currentFadeInColors[color&0x7FFF]; break;
case Decrease: color = gpu->currentFadeOutColors[color&0x7FFF]; break;
case Blend:
u16 backColor = HostReadWord(dst,x<<1);
color = gpu->blend(color,backColor);
break;
}
}
}
@ -1369,7 +1385,7 @@ INLINE void render_sprite_256(GPU * gpu, u8 spriteNum, u16 l, u8 * dst, u32 srca
{
color = LE_TO_LOCAL_16(pal[palette_entry]);
HostWriteWord(dst, (sprX<<1), color);
dst_alpha[sprX] = 15;
dst_alpha[sprX] = -1;
typeTab[sprX] = (alpha ? 1 : 0);
prioTab[sprX] = prio;
gpu->sprNum[sprX] = spriteNum;
@ -1399,7 +1415,7 @@ INLINE void render_sprite_16 ( GPU * gpu, u16 l, u8 * dst, u32 srcadr, u16 * pal
{
color = LE_TO_LOCAL_16(pal[palette_entry]);
HostWriteWord(dst, (sprX<<1), color);
dst_alpha[sprX] = 15;
dst_alpha[sprX] = -1;
typeTab[sprX] = (alpha ? 1 : 0);
prioTab[sprX] = prio;
}
@ -1654,7 +1670,7 @@ void GPU::_spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab)
if (colour && (prio<prioTab[sprX]))
{
HostWriteWord(dst, (sprX<<1), HostReadWord(pal, (colour<<1)));
dst_alpha[sprX] = 15;
dst_alpha[sprX] = -1;
typeTab[sprX] = spriteInfo->Mode;
prioTab[sprX] = prio;
}
@ -1757,7 +1773,7 @@ void GPU::_spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab)
else
{
HostWriteWord(dst, (sprX<<1), LE_TO_LOCAL_16(HostReadWord(pal, colour << 1)));
dst_alpha[sprX] = 15;
dst_alpha[sprX] = -1;
typeTab[sprX] = spriteInfo->Mode;
prioTab[sprX] = prio;
}