Implement BLDALPHA
Jeffrey Pfau jeffrey@endrift.com
Wed, 24 Apr 2013 01:16:03 -0700
2 files changed,
48 insertions(+),
2 deletions(-)
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -22,6 +22,7 @@
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer); static inline uint16_t _brighten(uint16_t color, int y); static inline uint16_t _darken(uint16_t color, int y); +static uint16_t _mix(int weightA, uint16_t colorA, int weightB, uint16_t colorB); static void _sortBackgrounds(struct GBAVideoSoftwareRenderer* renderer); static int _backgroundComparator(const void* a, const void* b);@@ -62,6 +63,8 @@ softwareRenderer->target2Bd = 0;
softwareRenderer->blendEffect = BLEND_NONE; memset(softwareRenderer->variantPalette, 0, sizeof(softwareRenderer->variantPalette)); + softwareRenderer->blda = 0; + softwareRenderer->bldb = 0; softwareRenderer->bldy = 0; for (i = 0; i < 4; ++i) {@@ -159,6 +162,16 @@ break;
case REG_BLDCNT: GBAVideoSoftwareRendererWriteBLDCNT(softwareRenderer, value); break; + case REG_BLDALPHA: + softwareRenderer->blda = value & 0x1F; + if (softwareRenderer->blda > 0x10) { + softwareRenderer->blda = 0x10; + } + softwareRenderer->bldb = (value >> 8) & 0x1F; + if (softwareRenderer->bldb > 0x10) { + softwareRenderer->bldb = 0x10; + } + break; case REG_BLDY: softwareRenderer->bldy = value & 0x1F; if (softwareRenderer->bldy > 0x10) {@@ -266,12 +279,26 @@ }
} static void _composite(struct GBAVideoSoftwareRenderer* renderer, int offset, int entry, struct PixelFlags flags) { - if (renderer->blendEffect == BLEND_NONE || !flags.target1) { + if (renderer->blendEffect == BLEND_NONE || (!flags.target1 && !flags.target2)) { renderer->row[offset] = renderer->d.palette[entry]; + renderer->flags[offset].finalized = 1; } else if (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN) { renderer->row[offset] = renderer->variantPalette[entry]; + renderer->flags[offset].finalized = 1; + } else if (renderer->blendEffect == BLEND_ALPHA) { + if (renderer->flags[offset].written) { + if (renderer->flags[offset].target1 && flags.target2) { + renderer->row[offset] = _mix(renderer->bldb, renderer->d.palette[entry], renderer->blda, renderer->row[offset]); + renderer->flags[offset].finalized = 1; + } else { + renderer->flags[offset].finalized = 1; + } + } else { + renderer->row[offset] = renderer->d.palette[entry]; + renderer->flags[offset].target1 = flags.target1; + } } - renderer->flags[offset].finalized = 1; + renderer->flags[offset].written = 1; } static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {@@ -343,6 +370,22 @@ color.r = color.r - (color.r * y) / 16;
color.g = color.g - (color.g * y) / 16; color.b = color.b - (color.b * y) / 16; return color.packed; +} + +static uint16_t _mix(int weightA, uint16_t colorA, int weightB, uint16_t colorB) { + union GBAColor ca = { .packed = colorA }; + union GBAColor cb = { .packed = colorB }; + + int r = (ca.r * weightA + cb.r * weightB) / 16; + ca.r = r > 0x1F ? 0x1F : r; + + int g = (ca.g * weightA + cb.g * weightB) / 16; + ca.g = g > 0x1F ? 0x1F : g; + + int b = (ca.b * weightA + cb.b * weightB) / 16; + ca.b = b > 0x1F ? 0x1F : b; + + return ca.packed; } static void _sortBackgrounds(struct GBAVideoSoftwareRenderer* renderer) {
M
src/gba/renderers/video-software.h
→
src/gba/renderers/video-software.h
@@ -37,6 +37,7 @@ BLEND_DARKEN = 3
}; struct PixelFlags { + unsigned written : 1; unsigned finalized : 1; unsigned target1 : 1; unsigned target2 : 1;@@ -60,6 +61,8 @@ unsigned target2Bd;
enum BlendEffect blendEffect; uint16_t variantPalette[512]; + uint16_t blda; + uint16_t bldb; uint16_t bldy; struct GBAVideoSoftwareBackground bg[4];