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; struct GBAObj obj;
int16_t y; int16_t y;
int16_t endY; int16_t endY;
int8_t index;
}; };
int GBAVideoRendererCleanOAM(struct GBAObj* oam, struct GBAVideoRendererSprite* sprites, int offsetY); int GBAVideoRendererCleanOAM(struct GBAObj* oam, struct GBAVideoRendererSprite* sprites, int offsetY);

View File

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

View File

@ -12,6 +12,7 @@ CXX_GUARD_START
#include <mgba/core/log.h> #include <mgba/core/log.h>
#include <mgba/core/timing.h> #include <mgba/core/timing.h>
#include <mgba/gba/interface.h>
mLOG_DECLARE_CATEGORY(GBA_VIDEO); mLOG_DECLARE_CATEGORY(GBA_VIDEO);
@ -192,6 +193,11 @@ struct GBAVideoRenderer {
bool disableBG[4]; bool disableBG[4];
bool disableOBJ; bool disableOBJ;
bool highlightBG[4];
bool highlightOBJ[128];
color_t highlightColor;
uint8_t highlightAmount;
}; };
struct GBAVideo { 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[2] = proxyRenderer->d.disableBG[2];
proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3]; proxyRenderer->backend->disableBG[3] = proxyRenderer->d.disableBG[3];
proxyRenderer->backend->disableOBJ = proxyRenderer->d.disableOBJ; 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) { if (item->address < GBA_VIDEO_VERTICAL_PIXELS) {
proxyRenderer->backend->drawScanline(proxyRenderer->backend, item->address); 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].y = y;
sprites[oamMax].endY = y + height; sprites[oamMax].endY = y + height;
sprites[oamMax].obj = obj; sprites[oamMax].obj = obj;
sprites[oamMax].index = i;
++oamMax; ++oamMax;
} }
} }

View File

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

View File

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

View File

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

View File

@ -62,6 +62,17 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->d.disableBG[3] = false; renderer->d.disableBG[3] = false;
renderer->d.disableOBJ = 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; renderer->temporaryBuffer = 0;
} }
@ -568,6 +579,13 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
softwareRenderer->windows[0].control.packed = 0xFF; 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) { if (softwareRenderer->blendDirty) {
_updatePalettes(softwareRenderer); _updatePalettes(softwareRenderer);
softwareRenderer->blendDirty = false; 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); _drawScanline(softwareRenderer, y);
if (softwareRenderer->target2Bd) { if (softwareRenderer->target2Bd) {
@ -828,7 +851,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
continue; continue;
} }
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, localY); int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, sprite->index, localY);
spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c); spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c);
} }
if (renderer->spriteCyclesRemaining <= 0) { if (renderer->spriteCyclesRemaining <= 0) {
@ -925,4 +948,12 @@ static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) {
renderer->variantPalette[i] = renderer->normalPalette[i]; 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);
}
}
} }