GBA Video: Support highlighting layers

This commit is contained in:
Vicki Pfau 2019-06-01 14:30:22 -07:00
parent 570f2c5f38
commit f41f3a8478
9 changed files with 77 additions and 3 deletions

View File

@ -16,6 +16,7 @@ struct GBAVideoRendererSprite {
struct GBAObj obj;
int16_t y;
int16_t endY;
int8_t index;
};
int GBAVideoRendererCleanOAM(struct GBAObj* oam, struct GBAVideoRendererSprite* sprites, int offsetY);

View File

@ -42,6 +42,7 @@ struct GBAVideoSoftwareBackground {
uint16_t mapCache[64];
int32_t offsetX;
int32_t offsetY;
bool highlight;
};
enum {
@ -105,6 +106,8 @@ struct GBAVideoSoftwareRenderer {
enum GBAVideoBlendEffect blendEffect;
color_t normalPalette[512];
color_t variantPalette[512];
color_t highlightPalette[512];
color_t highlightVariantPalette[512];
uint16_t blda;
uint16_t bldb;
@ -144,6 +147,8 @@ struct GBAVideoSoftwareRenderer {
int start;
int end;
uint8_t lastHighlightAmount;
};
void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);

View File

@ -12,6 +12,7 @@ CXX_GUARD_START
#include <mgba/core/log.h>
#include <mgba/core/timing.h>
#include <mgba/gba/interface.h>
mLOG_DECLARE_CATEGORY(GBA_VIDEO);
@ -192,6 +193,11 @@ struct GBAVideoRenderer {
bool disableBG[4];
bool disableOBJ;
bool highlightBG[4];
bool highlightOBJ[128];
color_t highlightColor;
uint8_t highlightAmount;
};
struct GBAVideo {

View File

@ -191,6 +191,12 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
proxyRenderer->backend->disableBG[2] = proxyRenderer->d.disableBG[2];
proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3];
proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ;
proxyRenderer->backend->highlightBG[0] = proxyRenderer->d.highlightBG[0];
proxyRenderer->backend->highlightBG[1] = proxyRenderer->d.highlightBG[1];
proxyRenderer->backend->highlightBG[2] = proxyRenderer->d.highlightBG[2];
proxyRenderer->backend->highlightBG[3] = proxyRenderer->d.highlightBG[3];
memcpy(proxyRenderer->backend->highlightOBJ, proxyRenderer->d.highlightOBJ, sizeof(proxyRenderer->backend->highlightOBJ));
proxyRenderer->backend->highlightAmount = proxyRenderer->d.highlightAmount;
if (item->address < GBA_VIDEO_VERTICAL_PIXELS) {
proxyRenderer->backend->drawScanline(proxyRenderer->backend, item->address);
}

View File

@ -25,6 +25,7 @@ int GBAVideoRendererCleanOAM(struct GBAObj* oam, struct GBAVideoRendererSprite*
sprites[oamMax].y = y;
sprites[oamMax].endY = y + height;
sprites[oamMax].obj = obj;
sprites[oamMax].index = i;
++oamMax;
}
}

View File

@ -482,8 +482,14 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
uint32_t charBase;
int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
color_t* mainPalette = renderer->normalPalette;
if (renderer->d.highlightAmount && background->highlight) {
mainPalette = renderer->highlightPalette;
}
if (variant) {
mainPalette = renderer->variantPalette;
if (renderer->d.highlightAmount && background->highlight) {
mainPalette = renderer->highlightVariantPalette;
}
}
color_t* palette = mainPalette;
PREPARE_OBJWIN;

View File

@ -127,7 +127,7 @@
renderer->row[outX] |= FLAG_OBJWIN; \
}
int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y) {
int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int index, int y) {
int width = GBAVideoObjSizes[GBAObjAttributesAGetShape(sprite->a) * 4 + GBAObjAttributesBGetSize(sprite->b)][0];
int height = GBAVideoObjSizes[GBAObjAttributesAGetShape(sprite->a) * 4 + GBAObjAttributesBGetSize(sprite->b)][1];
int start = renderer->start;
@ -167,10 +167,16 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
}
color_t* palette = &renderer->normalPalette[0x100];
if (renderer->d.highlightAmount && renderer->d.highlightOBJ[index]) {
palette = &renderer->highlightPalette[0x100];
}
color_t* objwinPalette = palette;
if (variant) {
palette = &renderer->variantPalette[0x100];
if (renderer->d.highlightAmount && renderer->d.highlightOBJ[index]) {
palette = &renderer->highlightVariantPalette[0x100];
}
if (GBAWindowControlIsBlendEnable(renderer->objwin.packed)) {
objwinPalette = palette;
}

View File

@ -26,7 +26,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer
void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer,
struct GBAVideoSoftwareBackground* background, int y);
int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int y);
int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int index, int y);
void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority);
static inline unsigned _brighten(unsigned color, int y);
@ -141,11 +141,17 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
int objwinForceEnable = 0; \
UNUSED(objwinForceEnable); \
color_t* objwinPalette = renderer->normalPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
objwinPalette = renderer->highlightPalette; \
} \
UNUSED(objwinPalette); \
if (objwinSlowPath) { \
if (background->target1 && GBAWindowControlIsBlendEnable(renderer->objwin.packed) && \
(renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN)) { \
objwinPalette = renderer->variantPalette; \
if (renderer->d.highlightAmount && background->highlight) { \
palette = renderer->highlightVariantPalette; \
} \
} \
switch (background->index) { \
case 0: \
@ -200,8 +206,14 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
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;

View File

@ -62,6 +62,17 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = false;
renderer->d.highlightBG[0] = false;
renderer->d.highlightBG[1] = false;
renderer->d.highlightBG[2] = false;
renderer->d.highlightBG[3] = false;
int i;
for (i = 0; i < 128; ++i) {
renderer->d.highlightOBJ[i] = false;
}
renderer->d.highlightColor = GBA_COLOR_WHITE;
renderer->d.highlightAmount = 0;
renderer->temporaryBuffer = 0;
}
@ -568,6 +579,13 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
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;
@ -595,6 +613,11 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
}
}
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->target2Bd) {
@ -828,7 +851,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
continue;
}
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, localY);
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, sprite->index, localY);
spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c);
}
if (renderer->spriteCyclesRemaining <= 0) {
@ -925,4 +948,12 @@ static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) {
renderer->variantPalette[i] = renderer->normalPalette[i];
}
}
unsigned highlightAmount = renderer->d.highlightAmount >> 4;
if (highlightAmount) {
for (i = 0; i < 512; ++i) {
renderer->highlightPalette[i] = _mix(0x10 - highlightAmount, renderer->normalPalette[i], highlightAmount, renderer->d.highlightColor);
renderer->highlightVariantPalette[i] = _mix(0x10 - highlightAmount, renderer->variantPalette[i], highlightAmount, renderer->d.highlightColor);
}
}
}