mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Backport many rendering changes from medusa
This commit is contained in:
parent
de16ea49c7
commit
0352125cad
|
@ -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; \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue