GBA Video: Allow alpha blending with per-pixel colors

This commit is contained in:
Vicki Pfau 2017-03-09 13:58:30 -05:00
parent 09c46ca2c4
commit 197f73cf85
7 changed files with 94 additions and 110 deletions

View File

@ -122,6 +122,8 @@ struct GBAVideoSoftwareRenderer {
uint32_t row[256];
uint32_t spriteLayer[256];
uint8_t alphaA[256];
uint8_t alphaB[256];
int32_t spriteCyclesRemaining;
// BLDCNT

View File

@ -372,6 +372,8 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend
GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer, y);
int spriteLayers = GBAVideoSoftwareRendererPreprocessSpriteLayer(softwareRenderer, y);
memset(softwareRenderer->alphaA, softwareRenderer->blda, sizeof(softwareRenderer->alphaA));
memset(softwareRenderer->alphaB, softwareRenderer->bldb, sizeof(softwareRenderer->alphaB));
int w;
unsigned priority;
@ -394,7 +396,14 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend
int x;
for (x = softwareRenderer->start; x < softwareRenderer->end; ++x) {
if (scanline[x] & 0xF8000000) {
_compositeBlendNoObjwin(softwareRenderer, &softwareRenderer->row[x], (scanline[x] & 0x00FFFFFF) | flags, softwareRenderer->row[x]);
if (flags & FLAG_TARGET_1) {
// TODO: More precise values
softwareRenderer->alphaA[x] = (scanline[x] >> 28) + 1;
softwareRenderer->alphaB[x] = 0x10 - softwareRenderer->alphaA[x];
_compositeBlendNoObjwin(softwareRenderer, x, (scanline[x] & 0x00FFFFFF) | flags, softwareRenderer->row[x]);
} else {
_compositeNoBlendNoObjwin(softwareRenderer, x, (scanline[x] & 0x00FFFFFF) | flags, softwareRenderer->row[x]);
}
}
}
} else {

View File

@ -34,11 +34,11 @@
}
#define MODE_2_LOOP(MOSAIC, COORD, BLEND, OBJWIN) \
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { \
for (outX = renderer->start; outX < renderer->end; ++outX) { \
x += background->dx; \
y += background->dy; \
\
uint32_t current = *pixel; \
uint32_t current = renderer->row[outX]; \
MOSAIC(COORD) \
if (pixelData) { \
COMPOSITE_256_ ## OBJWIN (BLEND, 0); \
@ -69,7 +69,6 @@ void GBAVideoSoftwareRendererDrawBackgroundMode2(struct GBAVideoSoftwareRenderer
uint8_t pixelData = 0;
int outX;
uint32_t* pixel;
if (!objwinSlowPath) {
if (!(flags & FLAG_TARGET_2)) {
@ -92,8 +91,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer
uint32_t color = renderer->normalPalette[0];
int outX;
uint32_t* pixel;
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
for (outX = renderer->start; outX < renderer->end; ++outX) {
BACKGROUND_BITMAP_ITERATE(renderer->masterEnd, VIDEO_VERTICAL_PIXELS);
if (!mosaicWait) {
@ -118,18 +116,18 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer
--mosaicWait;
}
uint32_t current = *pixel;
uint32_t current = renderer->row[outX];
if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != objwinOnly) {
unsigned mergedFlags = flags;
if (current & FLAG_OBJWIN) {
mergedFlags = objwinFlags;
}
if (!variant) {
_compositeBlendObjwin(renderer, pixel, color | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, color | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
_compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, _brighten(color, renderer->bldy) | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_DARKEN) {
_compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, _darken(color, renderer->bldy) | mergedFlags, current);
}
}
}
@ -145,8 +143,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer
}
int outX;
uint32_t* pixel;
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
for (outX = renderer->start; outX < renderer->end; ++outX) {
BACKGROUND_BITMAP_ITERATE(renderer->masterEnd, VIDEO_VERTICAL_PIXELS);
if (!mosaicWait) {
@ -157,17 +154,17 @@ void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer
--mosaicWait;
}
uint32_t current = *pixel;
uint32_t current = renderer->row[outX];
if (color && IS_WRITABLE(current)) {
if (!objwinSlowPath) {
_compositeBlendNoObjwin(renderer, pixel, palette[color] | flags, current);
_compositeBlendNoObjwin(renderer, outX, palette[color] | flags, current);
} else if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) {
color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette;
unsigned mergedFlags = flags;
if (current & FLAG_OBJWIN) {
mergedFlags = objwinFlags;
}
_compositeBlendObjwin(renderer, pixel, currentPalette[color] | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, currentPalette[color] | mergedFlags, current);
}
}
}
@ -183,8 +180,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer
}
int outX;
uint32_t* pixel;
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
for (outX = renderer->start; outX < renderer->end; ++outX) {
BACKGROUND_BITMAP_ITERATE(160, 128);
if (!mosaicWait) {
@ -208,18 +204,18 @@ void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer
--mosaicWait;
}
uint32_t current = *pixel;
uint32_t current = renderer->row[outX];
if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != objwinOnly) {
unsigned mergedFlags = flags;
if (current & FLAG_OBJWIN) {
mergedFlags = objwinFlags;
}
if (!variant) {
_compositeBlendObjwin(renderer, pixel, color | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, color | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
_compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, _brighten(color, renderer->bldy) | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_DARKEN) {
_compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | mergedFlags, current);
_compositeBlendObjwin(renderer, outX, _darken(color, renderer->bldy) | mergedFlags, current);
}
}
}

View File

@ -33,14 +33,14 @@
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData >>= 4 * mod8; \
for (; outX < end; ++outX, ++pixel) { \
for (; outX < end; ++outX) { \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
} \
} else { \
for (outX = end - 1; outX >= renderer->start; --outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
} \
outX = end; \
} \
}
@ -53,14 +53,12 @@
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
palette = &mainPalette[paletteData]; \
pixel = &renderer->row[outX]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
if (outX < renderer->start) { \
tileData >>= 4 * (renderer->start - outX); \
outX = renderer->start; \
pixel = &renderer->row[outX]; \
} \
for (; outX < renderer->end; ++outX, ++pixel) { \
for (; outX < renderer->end; ++outX) { \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
} \
} else { \
@ -70,14 +68,12 @@
end = -1; \
} \
outX = renderer->end - 1; \
pixel = &renderer->row[outX]; \
for (; outX > end; --outX, --pixel) { \
for (; outX > end; --outX) { \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
} \
/* Needed for consistency checks */ \
if (VIDEO_CHECKS) { \
outX = renderer->end; \
pixel = &renderer->row[outX]; \
} \
}
@ -142,7 +138,7 @@
} \
--mosaicWait; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
++pixel; \
++outX; \
} \
x = 0; \
}
@ -155,7 +151,7 @@
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
if (UNLIKELY(!vram)) { \
pixel += 8; \
outX += 8; \
continue; \
} \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
@ -180,7 +176,7 @@
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
} \
} \
pixel += 8; \
outX += 8; \
}
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256(BLEND, OBJWIN) \
@ -194,7 +190,7 @@
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
shift = 0; \
for (; outX < end2; ++outX, ++pixel) { \
for (; outX < end2; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
@ -203,18 +199,17 @@
if (LIKELY(vram)) { \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX < end; ++outX, ++pixel) { \
for (; outX < end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
} else { \
int start = outX; \
outX = end - 1; \
pixel = &renderer->row[outX]; \
if (LIKELY(vram)) { \
if (end2 > start) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX >= end2; --outX, --pixel) { \
for (; outX >= end2; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
charBase += 4; \
@ -223,12 +218,11 @@
\
if (LIKELY(vram)) { \
LOAD_32(tileData, charBase, vram); \
for (; outX >= renderer->start; --outX, --pixel) { \
for (; outX >= renderer->start; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
outX = end; \
pixel = &renderer->row[outX]; \
}
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \
@ -238,29 +232,27 @@
return; \
} \
int end = mod8 - 4; \
pixel = &renderer->row[outX]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
if (end > 0) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX < renderer->end - end; ++outX, ++pixel) { \
for (; outX < renderer->end - end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
charBase += 4; \
} \
\
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX < renderer->end; ++outX, ++pixel) { \
for (; outX < renderer->end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} else { \
int shift = (8 - mod8) & 0x3; \
int start = outX; \
outX = renderer->end - 1; \
pixel = &renderer->row[outX]; \
if (end > 0) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX >= start + 4; --outX, --pixel) { \
for (; outX >= start + 4; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
shift = 0; \
@ -268,13 +260,12 @@
\
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX >= start; --outX, --pixel) { \
for (; outX >= start; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
/* Needed for consistency checks */ \
if (VIDEO_CHECKS) { \
outX = renderer->end; \
pixel = &renderer->row[outX]; \
} \
}
@ -284,7 +275,7 @@
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
if (UNLIKELY(!vram)) { \
pixel += 8; \
outX += 8; \
continue; \
} \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
@ -295,7 +286,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
} \
pixel += 4; \
outX += 4; \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
@ -303,7 +294,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
} \
pixel += 4; \
outX += 4; \
} else { \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
@ -312,7 +303,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
pixel += 4; \
outX += 4; \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
@ -320,7 +311,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
pixel += 4; \
outX += 4; \
} \
}
@ -360,7 +351,7 @@
tileData |= tileData << 8; \
--mosaicWait; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
++pixel; \
++outX; \
} \
}
@ -377,7 +368,7 @@
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
shift = 0; \
for (; outX < end2; ++outX, ++pixel) { \
for (; outX < end2; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
@ -386,18 +377,17 @@
if (LIKELY(vram)) { \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX < end; ++outX, ++pixel) { \
for (; outX < end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
} else { \
int start = outX; \
outX = end - 1; \
pixel = &renderer->row[outX]; \
if (LIKELY(vram)) { \
if (end2 > start) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX >= end2; --outX, --pixel) { \
for (; outX >= end2; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
charBase += 4; \
@ -406,12 +396,11 @@
\
if (LIKELY(vram)) { \
LOAD_32(tileData, charBase, vram); \
for (; outX >= renderer->start; --outX, --pixel) { \
for (; outX >= renderer->start; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} \
outX = end; \
pixel = &renderer->row[outX]; \
}
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256EXT(BLEND, OBJWIN) \
@ -423,29 +412,27 @@
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
palette = &mainPalette[paletteData]; \
int end = mod8 - 4; \
pixel = &renderer->row[outX]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
if (end > 0) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX < renderer->end - end; ++outX, ++pixel) { \
for (; outX < renderer->end - end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
charBase += 4; \
} \
\
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
for (; outX < renderer->end; ++outX, ++pixel) { \
for (; outX < renderer->end; ++outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
} else { \
int shift = (8 - mod8) & 0x3; \
int start = outX; \
outX = renderer->end - 1; \
pixel = &renderer->row[outX]; \
if (end > 0) { \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX >= start + 4; --outX, --pixel) { \
for (; outX >= start + 4; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
shift = 0; \
@ -453,13 +440,12 @@
\
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
tileData >>= 8 * shift; \
for (; outX >= start; --outX, --pixel) { \
for (; outX >= start; --outX) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
/* Needed for consistency checks */ \
if (VIDEO_CHECKS) { \
outX = renderer->end; \
pixel = &renderer->row[outX]; \
} \
}
@ -471,7 +457,7 @@
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
if (UNLIKELY(!vram)) { \
pixel += 8; \
outX += 8; \
continue; \
} \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
@ -482,7 +468,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
} \
pixel += 4; \
outX += 4; \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
@ -490,7 +476,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
} \
pixel += 4; \
outX += 4; \
} else { \
LOAD_32(tileData, (charBase + 4) & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
@ -499,7 +485,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
pixel += 4; \
outX += 4; \
LOAD_32(tileData, charBase & VRAM_BLOCK_MASK, vram); \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
@ -507,7 +493,7 @@
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
} \
pixel += 4; \
outX += 4; \
} \
}
@ -549,12 +535,11 @@
tileData |= tileData << 8; \
--mosaicWait; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
++pixel; \
++outX; \
} \
}
#define DRAW_BACKGROUND_MODE_0(BPP, BLEND, OBJWIN) \
uint32_t* pixel = &renderer->row[outX]; \
if (background->mosaic && GBAMosaicControlGetBgH(renderer->mosaic)) { \
int mosaicH = GBAMosaicControlGetBgH(renderer->mosaic) + 1; \
int x; \
@ -590,13 +575,6 @@
} \
length -= end - renderer->start; \
} \
/*! TODO: Make sure these lines can be removed */ \
/*!*/ pixel = &renderer->row[outX]; \
outX += (tileEnd - tileX) * 8; \
/*!*/ if (VIDEO_CHECKS && UNLIKELY(outX > renderer->masterEnd)) { \
/*!*/ mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw would occur!"); \
/*!*/ return; \
/*!*/ } \
DRAW_BACKGROUND_MODE_0_TILES_ ## BPP (BLEND, OBJWIN) \
if (length & 0x7) { \
BACKGROUND_TEXT_SELECT_CHARACTER; \
@ -608,9 +586,6 @@
} \
DRAW_BACKGROUND_MODE_0_TILE_PREFIX_ ## BPP (BLEND, OBJWIN) \
} \
if (VIDEO_CHECKS && UNLIKELY(&renderer->row[outX] != pixel)) { \
mLOG(GBA_VIDEO, FATAL, "Background draw ended in the wrong place! Diff: %" PRIXPTR, &renderer->row[outX] - pixel); \
} \
if (VIDEO_CHECKS && UNLIKELY(outX > renderer->masterEnd)) { \
mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw occurred!"); \
return; \

View File

@ -402,7 +402,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority) {
int x;
uint32_t* pixel = &renderer->row[renderer->start];
uint32_t flags = FLAG_TARGET_2 * renderer->target2Obj;
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt);
@ -416,29 +415,29 @@ void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer*
}
if (objwinDisable) {
for (x = renderer->start; x < renderer->end; ++x, ++pixel) {
for (x = renderer->start; x < renderer->end; ++x) {
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel;
uint32_t current = renderer->row[x];
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && !(current & FLAG_OBJWIN) && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_compositeBlendObjwin(renderer, pixel, color | flags, current);
_compositeBlendObjwin(renderer, x, color | flags, current);
}
}
return;
} else if (objwinOnly) {
for (x = renderer->start; x < renderer->end; ++x, ++pixel) {
for (x = renderer->start; x < renderer->end; ++x) {
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel;
uint32_t current = renderer->row[x];
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (current & FLAG_OBJWIN) && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_compositeBlendObjwin(renderer, pixel, color | flags, current);
_compositeBlendObjwin(renderer, x, color | flags, current);
}
}
return;
} else {
for (x = renderer->start; x < renderer->end; ++x, ++pixel) {
for (x = renderer->start; x < renderer->end; ++x) {
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel;
uint32_t current = renderer->row[x];
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_compositeBlendObjwin(renderer, pixel, color | flags, current);
_compositeBlendObjwin(renderer, x, color | flags, current);
}
}
return;
@ -446,11 +445,11 @@ void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer*
} else if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed)) {
return;
}
for (x = renderer->start; x < renderer->end; ++x, ++pixel) {
for (x = renderer->start; x < renderer->end; ++x) {
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel;
uint32_t current = renderer->row[x];
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_compositeBlendNoObjwin(renderer, pixel, color | flags, current);
_compositeBlendNoObjwin(renderer, x, color | flags, current);
}
}
}

View File

@ -42,36 +42,36 @@ static unsigned _mix(int weightA, unsigned colorA, int weightB, unsigned colorB)
// The lower the number, the higher the priority, and sprites take precedence over backgrounds
// We want to do special processing if the color pixel is target 1, however
static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, int x, uint32_t color, uint32_t current) {
if (color >= current) {
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
color = _mix(renderer->alphaA[x], current, renderer->alphaB[x], color);
} else {
color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
}
} else {
color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN);
}
*pixel = color;
renderer->row[x] = color;
}
static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, int x, uint32_t color, uint32_t current) {
if (!IS_WRITABLE(current)) { \
return; \
} \
if (color >= current) {
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
color = _mix(renderer->alphaA[x], current, renderer->alphaB[x], color);
} else {
color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
}
} else {
color = color & ~FLAG_TARGET_2;
}
*pixel = color;
renderer->row[x] = color;
}
static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color,
static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, int x, uint32_t color,
uint32_t current) {
UNUSED(renderer);
if (color < current) {
@ -79,16 +79,16 @@ static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* rend
} else {
color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
}
*pixel = color;
renderer->row[x] = color;
}
static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color,
static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, int x, uint32_t color,
uint32_t current) {
UNUSED(renderer);
if (color >= current) {
color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
}
*pixel = color;
renderer->row[x] = color;
}
#define COMPOSITE_16_OBJWIN(BLEND, IDX) \
@ -101,11 +101,11 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
if (current & FLAG_OBJWIN) { \
mergedFlags = objwinFlags; \
} \
_composite ## BLEND ## Objwin(renderer, &pixel[IDX], color | mergedFlags, current); \
_composite ## BLEND ## Objwin(renderer, outX + IDX, color | mergedFlags, current); \
}
#define COMPOSITE_16_NO_OBJWIN(BLEND, IDX) \
_composite ## BLEND ## NoObjwin(renderer, &pixel[IDX], palette[pixelData] | flags, current);
_composite ## BLEND ## NoObjwin(renderer, outX + IDX, palette[pixelData] | flags, current);
#define COMPOSITE_256_OBJWIN(BLEND, IDX) \
if (!IS_WRITABLE(current)) { \
@ -117,14 +117,14 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
if (current & FLAG_OBJWIN) { \
mergedFlags = objwinFlags; \
} \
_composite ## BLEND ## Objwin(renderer, &pixel[IDX], color | mergedFlags, current); \
_composite ## BLEND ## Objwin(renderer, outX + IDX, color | mergedFlags, current); \
}
#define COMPOSITE_256_NO_OBJWIN COMPOSITE_16_NO_OBJWIN
#define BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, IDX) \
pixelData = tileData & 0xF; \
current = pixel[IDX]; \
current = renderer->row[outX + IDX]; \
if (pixelData && IS_WRITABLE(current)) { \
COMPOSITE_16_ ## OBJWIN (BLEND, IDX); \
} \
@ -132,7 +132,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
#define BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, IDX) \
pixelData = tileData & 0xFF; \
current = pixel[IDX]; \
current = renderer->row[outX + IDX]; \
if (pixelData && IS_WRITABLE(current)) { \
COMPOSITE_256_ ## OBJWIN (BLEND, IDX); \
} \

View File

@ -268,6 +268,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
if (softwareRenderer->bldb > 0x10) {
softwareRenderer->bldb = 0x10;
}
softwareRenderer->blendDirty = true;
value &= 0x1F1F;
break;
case REG_BLDY:
@ -768,7 +769,7 @@ void GBAVideoSoftwareRendererPostprocessBuffer(struct GBAVideoSoftwareRenderer*
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if (color & FLAG_TARGET_1) {
softwareRenderer->row[x] = _mix(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color);
softwareRenderer->row[x] = _mix(softwareRenderer->alphaB[x], backdrop, softwareRenderer->alphaA[x], color);
}
}
}
@ -842,6 +843,8 @@ int GBAVideoSoftwareRendererPreprocessSpriteLayer(struct GBAVideoSoftwareRendere
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) {
int i;
memset(renderer->alphaA, renderer->blda, sizeof(renderer->alphaA));
memset(renderer->alphaB, renderer->bldb, sizeof(renderer->alphaB));
if (renderer->blendEffect == BLEND_BRIGHTEN) {
for (i = 0; i < 512; ++i) {
renderer->variantPalette[i] = _brighten(renderer->normalPalette[i], renderer->bldy);