all repos — mgba @ 197f73cf85d8b81da9c9620881991543e9d77b5f

mGBA Game Boy Advance Emulator

GBA Video: Allow alpha blending with per-pixel colors
Vicki Pfau vi@endrift.com
Thu, 09 Mar 2017 13:58:30 -0500
commit

197f73cf85d8b81da9c9620881991543e9d77b5f

parent

09c46ca2c4e019d25e5e0301db738d557605e105

M include/mgba/internal/gba/renderers/video-software.hinclude/mgba/internal/gba/renderers/video-software.h

@@ -122,6 +122,8 @@ uint32_t dispcnt;

uint32_t row[256]; uint32_t spriteLayer[256]; + uint8_t alphaA[256]; + uint8_t alphaB[256]; int32_t spriteCyclesRemaining; // BLDCNT
M src/ds/renderers/software.csrc/ds/renderers/software.c

@@ -372,6 +372,8 @@ }

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 @@ flags |= FLAG_TARGET_1 * (softwareRenderer->bg[0].target1 && softwareRenderer->blendEffect == BLEND_ALPHA && GBAWindowControlIsBlendEnable(softwareRenderer->currentWindow.packed));

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 {
M src/gba/renderers/software-bg.csrc/gba/renderers/software-bg.c

@@ -34,11 +34,11 @@ --mosaicWait; \

} #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 @@ uint8_t mapData;

uint8_t pixelData = 0; int outX; - uint32_t* pixel; if (!objwinSlowPath) { if (!(flags & FLAG_TARGET_2)) {

@@ -92,8 +91,7 @@

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 @@ } else {

--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 @@ offset = 0xA000;

} 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 @@ } else {

--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 @@ offset = 0xA000;

} 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 @@ } else {

--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); } } }
M src/gba/renderers/software-mode0.csrc/gba/renderers/software-mode0.c

@@ -33,14 +33,14 @@ if (LIKELY(vram)) { \

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 @@ if (end < -1) { \

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 = mosaicH; \

} \ --mosaicWait; \ BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \ - ++pixel; \ + ++outX; \ } \ x = 0; \ }

@@ -155,7 +151,7 @@ palette = &mainPalette[paletteData]; \

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, 1); \

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 @@ if (end2 > outX) { \

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 @@ if (UNLIKELY(!vram)) { \

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 @@ BACKGROUND_TEXT_SELECT_CHARACTER; \

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, 1); \

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, 1); \

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, 2); \

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, 2); \

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 @@ if (end2 > outX) { \

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 @@ palette = &mainPalette[paletteData]; \

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, 1); \

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, 1); \

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, 2); \

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, 2); \

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 @@ return; \

} \ 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; \

@@ -607,9 +585,6 @@ mLOG(GBA_VIDEO, FATAL, "Invariant doesn't hold in background draw!"); \

return; \ } \ 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!"); \
M src/gba/renderers/software-obj.csrc/gba/renderers/software-obj.c

@@ -402,7 +402,6 @@ }

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 @@ return;

} 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 @@ }

} 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); } } }
M src/gba/renderers/software-private.hsrc/gba/renderers/software-private.h

@@ -42,36 +42,36 @@ // We stash the priority on the top bits so we can do a one-operator comparison

// 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 @@ color |= (current & FLAG_OBJWIN);

} 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 @@ unsigned mergedFlags = flags; \

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 @@ unsigned mergedFlags = flags; \

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 @@ tileData >>= 4;

#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); \ } \
M src/gba/renderers/video-software.csrc/gba/renderers/video-software.c

@@ -268,6 +268,7 @@ softwareRenderer->bldb = (value >> 8) & 0x1F;

if (softwareRenderer->bldb > 0x10) { softwareRenderer->bldb = 0x10; } + softwareRenderer->blendDirty = true; value &= 0x1F1F; break; case REG_BLDY:

@@ -768,7 +769,7 @@ int end = softwareRenderer->windows[w].endX;

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 @@ }

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);