From 7b5a9b4f65f5ba6687ccc368359c5add20906d92 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Oct 2017 19:52:48 -0700 Subject: [PATCH] GBA Video: OBJWIN can change blend params after OBJ is drawn (fixes #921) --- CHANGES | 1 + src/gba/renderers/software-obj.c | 18 +++++++++--------- src/gba/renderers/software-private.h | 8 ++++---- src/gba/renderers/video-software.c | 12 ++++++++++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index 9d3a35474..759dd5915 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Bugfixes: - GBA DMA: ROM reads are forced to increment - GB Video: Only trigger STAT write IRQs when screen is on (fixes mgba.io/i/912) - GBA Cheats: Fix PARv3 slide codes (fixes mgba.io/i/919) + - GBA Video: OBJWIN can change blend params after OBJ is drawn (fixes mgba.io/i/921) 0.6.1: (2017-10-01) Bugfixes: diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c index a4bdcf228..354d8f671 100644 --- a/src/gba/renderers/software-obj.c +++ b/src/gba/renderers/software-obj.c @@ -156,26 +156,26 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re return 0; } + int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed); int variant = renderer->target1Obj && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); - if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) { - int target2 = renderer->target2Bd << 4; - target2 |= renderer->bg[0].target2 << (renderer->bg[0].priority); - target2 |= renderer->bg[1].target2 << (renderer->bg[1].priority); - target2 |= renderer->bg[2].target2 << (renderer->bg[2].priority); - target2 |= renderer->bg[3].target2 << (renderer->bg[3].priority); - if ((1 << GBAObjAttributesCGetPriority(sprite->c)) <= target2) { + if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT || objwinSlowPath) { + int target2 = renderer->target2Bd; + target2 |= renderer->bg[0].target2; + target2 |= renderer->bg[1].target2; + target2 |= renderer->bg[2].target2; + target2 |= renderer->bg[3].target2; + if (target2) { flags |= FLAG_REBLEND; variant = 0; - } else if (!target2) { + } else { flags &= ~FLAG_TARGET_1; } } color_t* palette = &renderer->normalPalette[0x100]; color_t* objwinPalette = palette; - int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed); if (variant) { palette = &renderer->variantPalette[0x100]; diff --git a/src/gba/renderers/software-private.h b/src/gba/renderers/software-private.h index 1a530abe5..4e4e19166 100644 --- a/src/gba/renderers/software-private.h +++ b/src/gba/renderers/software-private.h @@ -43,7 +43,7 @@ static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* render if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) { color = _mix(renderer->blda, current, renderer->bldb, color); } else { - color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND); + color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN)); } } else { color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN); @@ -59,7 +59,7 @@ static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* rend if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) { color = _mix(renderer->blda, current, renderer->bldb, color); } else { - color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND); + color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN)); } } else { color = color & ~FLAG_TARGET_2; @@ -73,7 +73,7 @@ static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* rend if (color < current) { color |= (current & FLAG_OBJWIN); } else { - color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND); + color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN)); } *pixel = color; } @@ -82,7 +82,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re uint32_t current) { UNUSED(renderer); if (color >= current) { - color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND); + color = (current & 0x00FFFFFF) | (current & (FLAG_REBLEND | FLAG_OBJWIN)); } *pixel = color; } diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 70dac8811..1b0017d30 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -568,6 +568,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render } if (softwareRenderer->target1Obj && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) { x = 0; + uint32_t mask = 0xFF000000 & ~FLAG_OBJWIN; + uint32_t match = FLAG_REBLEND; + if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) { + mask |= FLAG_OBJWIN; + if (GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed)) { + match |= FLAG_OBJWIN; + } + } for (w = 0; w < softwareRenderer->nWindows; ++w) { if (!GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) { continue; @@ -576,14 +584,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render if (softwareRenderer->blendEffect == BLEND_DARKEN) { for (; x < end; ++x) { uint32_t color = softwareRenderer->row[x]; - if ((color & 0xFF000000) == FLAG_REBLEND) { + if ((color & mask) == match) { softwareRenderer->row[x] = _darken(color, softwareRenderer->bldy); } } } else if (softwareRenderer->blendEffect == BLEND_BRIGHTEN) { for (; x < end; ++x) { uint32_t color = softwareRenderer->row[x]; - if ((color & 0xFF000000) == FLAG_REBLEND) { + if ((color & mask) == match) { softwareRenderer->row[x] = _brighten(color, softwareRenderer->bldy); } }