GBA Video: Backport many rendering changes from medusa

This commit is contained in:
Vicki Pfau 2021-06-30 00:01:09 -07:00
parent de16ea49c7
commit 0352125cad
3 changed files with 261 additions and 245 deletions

View File

@ -8,53 +8,6 @@
#include <mgba/core/interface.h>
#include <mgba/internal/gba/gba.h>
#define BACKGROUND_BITMAP_INIT \
int32_t x = background->sx + (renderer->start - 1) * background->dx; \
int32_t y = background->sy + (renderer->start - 1) * background->dy; \
int mosaicH = 0; \
int mosaicWait = 0; \
int32_t localX; \
int32_t localY; \
if (background->mosaic) { \
int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; \
mosaicH = GBAMosaicControlGetBgH(renderer->mosaic) + 1; \
mosaicWait = (mosaicH - renderer->start + GBA_VIDEO_HORIZONTAL_PIXELS * mosaicH) % mosaicH; \
int32_t startX = renderer->start - (renderer->start % mosaicH); \
--mosaicH; \
localX = -(inY % mosaicV) * background->dmx; \
localY = -(inY % mosaicV) * background->dmy; \
x += localX; \
y += localY; \
localX += background->sx + startX * background->dx; \
localY += background->sy + startX * background->dy; \
} \
\
uint32_t flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \
flags |= FLAG_TARGET_2 * background->target2; \
int objwinFlags = FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \
GBAWindowControlIsBlendEnable(renderer->objwin.packed)); \
objwinFlags |= flags; \
flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \
GBAWindowControlIsBlendEnable(renderer->currentWindow.packed)); \
if (renderer->blendEffect == BLEND_ALPHA && renderer->blda == 0x10 && renderer->bldb == 0) { \
flags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \
objwinFlags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \
} \
int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && \
(renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \
color_t* palette = renderer->normalPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
palette = renderer->highlightPalette; \
} \
if (variant) { \
palette = renderer->variantPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
palette = renderer->highlightVariantPalette; \
} \
} \
UNUSED(palette); \
PREPARE_OBJWIN;
#define BACKGROUND_BITMAP_ITERATE(W, H) \
x += background->dx; \
y += background->dy; \
@ -75,22 +28,19 @@
localX = x; \
localY = y;
#define MODE_2_MOSAIC(COORD) \
if (!mosaicWait) { \
COORD \
mapData = screenBase[(localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; \
pixelData = charBase[(mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; \
\
mosaicWait = mosaicH; \
} else { \
--mosaicWait; \
}
#define MODE_2_NO_MOSAIC(COORD) \
COORD \
mapData = screenBase[(localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; \
pixelData = charBase[(mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)];
#define MODE_2_MOSAIC(COORD) \
if (!mosaicWait) { \
MODE_2_NO_MOSAIC(COORD) \
mosaicWait = mosaicH; \
} else { \
--mosaicWait; \
}
#define MODE_2_LOOP(MOSAIC, COORD, BLEND, OBJWIN) \
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { \
x += background->dx; \

View File

@ -166,6 +166,60 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
} \
}
#define BACKGROUND_BITMAP_INIT \
int32_t x = background->sx + (renderer->start - 1) * background->dx; \
int32_t y = background->sy + (renderer->start - 1) * background->dy; \
int mosaicH = 0; \
int mosaicWait = 0; \
int32_t localX; \
int32_t localY; \
if (background->mosaic) { \
int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; \
mosaicH = GBAMosaicControlGetBgH(renderer->mosaic) + 1; \
mosaicWait = (mosaicH - renderer->start + GBA_VIDEO_HORIZONTAL_PIXELS * mosaicH) % mosaicH; \
int32_t startX = renderer->start - (renderer->start % mosaicH); \
--mosaicH; \
localX = -(inY % mosaicV) * background->dmx; \
localY = -(inY % mosaicV) * background->dmy; \
x += localX; \
y += localY; \
localX += background->sx + startX * background->dx; \
localY += background->sy + startX * background->dy; \
} \
\
uint32_t flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \
flags |= FLAG_TARGET_2 * background->target2; \
int objwinFlags = FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \
GBAWindowControlIsBlendEnable(renderer->objwin.packed)); \
objwinFlags |= flags; \
flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \
GBAWindowControlIsBlendEnable(renderer->currentWindow.packed)); \
if (renderer->blendEffect == BLEND_ALPHA && renderer->blda == 0x10 && renderer->bldb == 0) { \
flags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \
objwinFlags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \
} \
int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && \
(renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \
color_t* palette = renderer->normalPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
palette = renderer->highlightPalette; \
} \
if (variant) { \
palette = renderer->variantPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
palette = renderer->highlightVariantPalette; \
} \
} \
UNUSED(palette); \
PREPARE_OBJWIN;
#define TEST_LAYER_ENABLED(X) \
!softwareRenderer->d.disableBG[X] && \
(softwareRenderer->bg[X].enabled == 4 && \
(GBAWindowControlIsBg ## X ## Enable(softwareRenderer->currentWindow.packed) || \
(GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt) && GBAWindowControlIsBg ## X ## Enable (softwareRenderer->objwin.packed))) && \
softwareRenderer->bg[X].priority == priority)
static inline unsigned _brighten(unsigned color, int y) {
unsigned c = 0;
unsigned a;

View File

@ -35,7 +35,9 @@ static void GBAVideoSoftwareRendererWriteBGY_LO(struct GBAVideoSoftwareBackgroun
static void GBAVideoSoftwareRendererWriteBGY_HI(struct GBAVideoSoftwareBackground* bg, uint16_t value);
static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* renderer, uint16_t value);
static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y);
static void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* renderer, int y);
static void GBAVideoSoftwareRendererPostprocessBuffer(struct GBAVideoSoftwareRenderer* renderer);
static int GBAVideoSoftwareRendererPreprocessSpriteLayer(struct GBAVideoSoftwareRenderer* renderer, int y);
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer);
@ -562,123 +564,87 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
return;
}
int x;
for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) {
softwareRenderer->spriteLayer[x] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 1] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 2] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 3] = FLAG_UNWRITTEN;
}
softwareRenderer->windows[0].endX = GBA_VIDEO_HORIZONTAL_PIXELS;
softwareRenderer->nWindows = 1;
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
softwareRenderer->windows[0].control = softwareRenderer->winout;
if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[1]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[1], y);
}
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !renderer->disableWIN[0]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[0], y);
}
} else {
softwareRenderer->windows[0].control.packed = 0xFF;
}
if (softwareRenderer->lastHighlightAmount != softwareRenderer->d.highlightAmount) {
softwareRenderer->lastHighlightAmount = softwareRenderer->d.highlightAmount;
if (softwareRenderer->lastHighlightAmount) {
softwareRenderer->blendDirty = true;
}
}
if (softwareRenderer->blendDirty) {
_updatePalettes(softwareRenderer);
softwareRenderer->blendDirty = false;
}
softwareRenderer->forceTarget1 = false;
GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer, y);
softwareRenderer->spriteCyclesRemaining = GBARegisterDISPCNTIsHblankIntervalFree(softwareRenderer->dispcnt) ? OBJ_HBLANK_FREE_LENGTH : OBJ_LENGTH;
int spriteLayers = GBAVideoSoftwareRendererPreprocessSpriteLayer(softwareRenderer, y);
int w;
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
// TOOD: handle objwin on backdrop
uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0];
} else {
backdrop |= softwareRenderer->variantPalette[0];
}
int end = softwareRenderer->windows[w].endX;
for (; x < end - 3; x += 4) {
softwareRenderer->row[x] = backdrop;
softwareRenderer->row[x + 1] = backdrop;
softwareRenderer->row[x + 2] = backdrop;
softwareRenderer->row[x + 3] = backdrop;
}
for (; x < end; ++x) {
softwareRenderer->row[x] = backdrop;
}
}
softwareRenderer->bg[0].highlight = softwareRenderer->d.highlightBG[0];
softwareRenderer->bg[1].highlight = softwareRenderer->d.highlightBG[1];
softwareRenderer->bg[2].highlight = softwareRenderer->d.highlightBG[2];
softwareRenderer->bg[3].highlight = softwareRenderer->d.highlightBG[3];
_drawScanline(softwareRenderer, y);
if ((softwareRenderer->forceTarget1 || softwareRenderer->bg[0].target1 || softwareRenderer->bg[1].target1 || softwareRenderer->bg[2].target1 || softwareRenderer->bg[3].target1) && softwareRenderer->target2Bd) {
x = 0;
unsigned priority;
for (priority = 0; priority < 4; ++priority) {
softwareRenderer->end = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
uint32_t backdrop = 0;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0];
} else {
backdrop |= softwareRenderer->variantPalette[0];
softwareRenderer->start = softwareRenderer->end;
softwareRenderer->end = softwareRenderer->windows[w].endX;
softwareRenderer->currentWindow = softwareRenderer->windows[w].control;
if (spriteLayers & (1 << priority)) {
GBAVideoSoftwareRendererPostprocessSprite(softwareRenderer, priority);
}
int end = softwareRenderer->windows[w].endX;
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if (color & FLAG_TARGET_1) {
softwareRenderer->row[x] = mColorMix5Bit(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color);
if (TEST_LAYER_ENABLED(0) && GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) < 2) {
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[0], y);
}
if (TEST_LAYER_ENABLED(1) && GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) < 2) {
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[1], y);
}
if (TEST_LAYER_ENABLED(2)) {
switch (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt)) {
case 0:
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[2], y);
break;
case 1:
case 2:
GBAVideoSoftwareRendererDrawBackgroundMode2(softwareRenderer, &softwareRenderer->bg[2], y);
break;
case 3:
GBAVideoSoftwareRendererDrawBackgroundMode3(softwareRenderer, &softwareRenderer->bg[2], y);
break;
case 4:
GBAVideoSoftwareRendererDrawBackgroundMode4(softwareRenderer, &softwareRenderer->bg[2], y);
break;
case 5:
GBAVideoSoftwareRendererDrawBackgroundMode5(softwareRenderer, &softwareRenderer->bg[2], y);
break;
}
}
}
}
if (softwareRenderer->forceTarget1 && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) {
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
int end = softwareRenderer->windows[w].endX;
uint32_t mask = FLAG_REBLEND | FLAG_IS_BACKGROUND;
uint32_t match = FLAG_REBLEND;
bool objBlend = GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed);
bool winBlend = GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed);
if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt) && objBlend != winBlend) {
mask |= FLAG_OBJWIN;
if (objBlend) {
match |= FLAG_OBJWIN;
}
} else if (!winBlend) {
x = end;
continue;
}
if (softwareRenderer->blendEffect == BLEND_DARKEN) {
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
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 & mask) == match) {
softwareRenderer->row[x] = _brighten(color, softwareRenderer->bldy);
}
if (TEST_LAYER_ENABLED(3)) {
switch (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt)) {
case 0:
GBAVideoSoftwareRendererDrawBackgroundMode0(softwareRenderer, &softwareRenderer->bg[3], y);
break;
case 2:
GBAVideoSoftwareRendererDrawBackgroundMode2(softwareRenderer, &softwareRenderer->bg[3], y);
break;
}
}
}
}
GBAVideoSoftwareRendererPostprocessBuffer(softwareRenderer);
if (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) != 0) {
softwareRenderer->bg[2].sx += softwareRenderer->bg[2].dmx;
softwareRenderer->bg[2].sy += softwareRenderer->bg[2].dmy;
softwareRenderer->bg[3].sx += softwareRenderer->bg[3].dmx;
softwareRenderer->bg[3].sy += softwareRenderer->bg[3].dmy;
}
if (softwareRenderer->bg[0].enabled > 0 && softwareRenderer->bg[0].enabled < 4) {
++softwareRenderer->bg[0].enabled;
DIRTY_SCANLINE(softwareRenderer, y);
}
if (softwareRenderer->bg[1].enabled > 0 && softwareRenderer->bg[1].enabled < 4) {
++softwareRenderer->bg[1].enabled;
DIRTY_SCANLINE(softwareRenderer, y);
}
if (softwareRenderer->bg[2].enabled > 0 && softwareRenderer->bg[2].enabled < 4) {
++softwareRenderer->bg[2].enabled;
DIRTY_SCANLINE(softwareRenderer, y);
}
if (softwareRenderer->bg[3].enabled > 0 && softwareRenderer->bg[3].enabled < 4) {
++softwareRenderer->bg[3].enabled;
DIRTY_SCANLINE(softwareRenderer, y);
}
int x;
if (softwareRenderer->greenswap) {
for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) {
row[x] = softwareRenderer->row[x] & (M_COLOR_RED | M_COLOR_BLUE);
@ -828,14 +794,132 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer*
}
}
#define TEST_LAYER_ENABLED(X) \
!renderer->d.disableBG[X] && \
(renderer->bg[X].enabled == 4 && \
(GBAWindowControlIsBg ## X ## Enable(renderer->currentWindow.packed) || \
(GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlIsBg ## X ## Enable (renderer->objwin.packed))) && \
renderer->bg[X].priority == priority)
void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* softwareRenderer, int y) {
int x;
for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) {
softwareRenderer->spriteLayer[x] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 1] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 2] = FLAG_UNWRITTEN;
softwareRenderer->spriteLayer[x + 3] = FLAG_UNWRITTEN;
}
static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
softwareRenderer->windows[0].endX = GBA_VIDEO_HORIZONTAL_PIXELS;
softwareRenderer->nWindows = 1;
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) {
softwareRenderer->windows[0].control = softwareRenderer->winout;
if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[1]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[1], y);
}
if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[0]) {
_breakWindow(softwareRenderer, &softwareRenderer->winN[0], y);
}
} else {
softwareRenderer->windows[0].control.packed = 0xFF;
}
GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer);
if (softwareRenderer->lastHighlightAmount != softwareRenderer->d.highlightAmount) {
softwareRenderer->lastHighlightAmount = softwareRenderer->d.highlightAmount;
if (softwareRenderer->lastHighlightAmount) {
softwareRenderer->blendDirty = true;
}
}
if (softwareRenderer->blendDirty) {
_updatePalettes(softwareRenderer);
softwareRenderer->blendDirty = false;
}
softwareRenderer->forceTarget1 = false;
int w;
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
// TOOD: handle objwin on backdrop
uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0];
} else {
backdrop |= softwareRenderer->variantPalette[0];
}
int end = softwareRenderer->windows[w].endX;
for (; x & 3; ++x) {
softwareRenderer->row[x] = backdrop;
}
for (; x < end - 3; x += 4) {
softwareRenderer->row[x] = backdrop;
softwareRenderer->row[x + 1] = backdrop;
softwareRenderer->row[x + 2] = backdrop;
softwareRenderer->row[x + 3] = backdrop;
}
for (; x < end; ++x) {
softwareRenderer->row[x] = backdrop;
}
}
softwareRenderer->bg[0].highlight = softwareRenderer->d.highlightBG[0];
softwareRenderer->bg[1].highlight = softwareRenderer->d.highlightBG[1];
softwareRenderer->bg[2].highlight = softwareRenderer->d.highlightBG[2];
softwareRenderer->bg[3].highlight = softwareRenderer->d.highlightBG[3];
}
void GBAVideoSoftwareRendererPostprocessBuffer(struct GBAVideoSoftwareRenderer* softwareRenderer) {
int x, w;
if ((softwareRenderer->forceTarget1 || softwareRenderer->bg[0].target1 || softwareRenderer->bg[1].target1 || softwareRenderer->bg[2].target1 || softwareRenderer->bg[3].target1) && softwareRenderer->target2Bd) {
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
uint32_t backdrop = 0;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed)) {
backdrop |= softwareRenderer->normalPalette[0];
} else {
backdrop |= softwareRenderer->variantPalette[0];
}
int end = softwareRenderer->windows[w].endX;
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if (color & FLAG_TARGET_1) {
softwareRenderer->row[x] = mColorMix5Bit(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color);
}
}
}
}
if (softwareRenderer->forceTarget1 && (softwareRenderer->blendEffect == BLEND_DARKEN || softwareRenderer->blendEffect == BLEND_BRIGHTEN)) {
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
int end = softwareRenderer->windows[w].endX;
uint32_t mask = FLAG_REBLEND | FLAG_IS_BACKGROUND;
uint32_t match = FLAG_REBLEND;
bool objBlend = GBAWindowControlIsBlendEnable(softwareRenderer->objwin.packed);
bool winBlend = GBAWindowControlIsBlendEnable(softwareRenderer->windows[w].control.packed);
if (GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt) && objBlend != winBlend) {
mask |= FLAG_OBJWIN;
if (objBlend) {
match |= FLAG_OBJWIN;
}
} else if (!winBlend) {
x = end;
continue;
}
if (softwareRenderer->blendEffect == BLEND_DARKEN) {
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
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 & mask) == match) {
softwareRenderer->row[x] = _brighten(color, softwareRenderer->bldy);
}
}
}
}
}
}
int GBAVideoSoftwareRendererPreprocessSpriteLayer(struct GBAVideoSoftwareRenderer* renderer, int y) {
int w;
int spriteLayers = 0;
if (GBARegisterDISPCNTIsObjEnable(renderer->dispcnt) && !renderer->d.disableOBJ) {
@ -843,7 +927,6 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
renderer->oamMax = GBAVideoRendererCleanOAM(renderer->d.oam->obj, renderer->sprites, renderer->objOffsetY);
renderer->oamDirty = false;
}
renderer->spriteCyclesRemaining = GBARegisterDISPCNTIsHblankIntervalFree(renderer->dispcnt) ? OBJ_HBLANK_FREE_LENGTH : OBJ_LENGTH;
int mosaicV = GBAMosaicControlGetObjV(renderer->mosaic) + 1;
int mosaicY = y - (y % mosaicV);
int i;
@ -881,78 +964,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
}
}
}
unsigned priority;
for (priority = 0; priority < 4; ++priority) {
renderer->end = 0;
for (w = 0; w < renderer->nWindows; ++w) {
renderer->start = renderer->end;
renderer->end = renderer->windows[w].endX;
renderer->currentWindow = renderer->windows[w].control;
if (spriteLayers & (1 << priority)) {
GBAVideoSoftwareRendererPostprocessSprite(renderer, priority);
}
if (TEST_LAYER_ENABLED(0) && GBARegisterDISPCNTGetMode(renderer->dispcnt) < 2) {
GBAVideoSoftwareRendererDrawBackgroundMode0(renderer, &renderer->bg[0], y);
}
if (TEST_LAYER_ENABLED(1) && GBARegisterDISPCNTGetMode(renderer->dispcnt) < 2) {
GBAVideoSoftwareRendererDrawBackgroundMode0(renderer, &renderer->bg[1], y);
}
if (TEST_LAYER_ENABLED(2)) {
switch (GBARegisterDISPCNTGetMode(renderer->dispcnt)) {
case 0:
GBAVideoSoftwareRendererDrawBackgroundMode0(renderer, &renderer->bg[2], y);
break;
case 1:
case 2:
GBAVideoSoftwareRendererDrawBackgroundMode2(renderer, &renderer->bg[2], y);
break;
case 3:
GBAVideoSoftwareRendererDrawBackgroundMode3(renderer, &renderer->bg[2], y);
break;
case 4:
GBAVideoSoftwareRendererDrawBackgroundMode4(renderer, &renderer->bg[2], y);
break;
case 5:
GBAVideoSoftwareRendererDrawBackgroundMode5(renderer, &renderer->bg[2], y);
break;
}
}
if (TEST_LAYER_ENABLED(3)) {
switch (GBARegisterDISPCNTGetMode(renderer->dispcnt)) {
case 0:
GBAVideoSoftwareRendererDrawBackgroundMode0(renderer, &renderer->bg[3], y);
break;
case 2:
GBAVideoSoftwareRendererDrawBackgroundMode2(renderer, &renderer->bg[3], y);
break;
}
}
}
}
if (GBARegisterDISPCNTGetMode(renderer->dispcnt) != 0) {
renderer->bg[2].sx += renderer->bg[2].dmx;
renderer->bg[2].sy += renderer->bg[2].dmy;
renderer->bg[3].sx += renderer->bg[3].dmx;
renderer->bg[3].sy += renderer->bg[3].dmy;
}
if (renderer->bg[0].enabled > 0 && renderer->bg[0].enabled < 4) {
++renderer->bg[0].enabled;
DIRTY_SCANLINE(renderer, y);
}
if (renderer->bg[1].enabled > 0 && renderer->bg[1].enabled < 4) {
++renderer->bg[1].enabled;
DIRTY_SCANLINE(renderer, y);
}
if (renderer->bg[2].enabled > 0 && renderer->bg[2].enabled < 4) {
++renderer->bg[2].enabled;
DIRTY_SCANLINE(renderer, y);
}
if (renderer->bg[3].enabled > 0 && renderer->bg[3].enabled < 4) {
++renderer->bg[3].enabled;
DIRTY_SCANLINE(renderer, y);
}
return spriteLayers;
}
static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) {