GBA Video: Support highlighting layers
jump to
@@ -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);
@@ -42,6 +42,7 @@ int yCache;
uint16_t mapCache[64]; int32_t offsetX; int32_t offsetY; + bool highlight; }; enum {@@ -105,6 +106,8 @@ bool blendDirty;
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 @@ int nextY;
int start; int end; + + uint8_t lastHighlightAmount; }; void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer);
@@ -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 mCacheSet* cache;
bool disableBG[4]; bool disableOBJ; + + bool highlightBG[4]; + bool highlightOBJ[128]; + color_t highlightColor; + uint8_t highlightAmount; }; struct GBAVideo {
@@ -191,6 +191,12 @@ proxyRenderer->backend->disableBG[1] = proxyRenderer->d.disableBG[1];
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); }
@@ -25,6 +25,7 @@ int y = GBAObjAttributesAGetY(obj.a) + offsetY;
sprites[oamMax].y = y; sprites[oamMax].endY = y + height; sprites[oamMax].obj = obj; + sprites[oamMax].index = i; ++oamMax; } }
@@ -482,8 +482,14 @@ uint32_t screenBase;
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;
@@ -127,7 +127,7 @@ if (tileData) { \
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 @@ }
} 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; }
@@ -26,7 +26,7 @@ struct GBAVideoSoftwareBackground* background, int y);
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 @@ int objwinOnly = 0; \
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 @@ } \
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;
@@ -62,6 +62,17 @@ renderer->d.disableBG[2] = false;
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 @@ } 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;@@ -594,6 +612,11 @@ 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);@@ -828,7 +851,7 @@ if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed) && !GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
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) {@@ -923,6 +946,14 @@ }
} else { for (i = 0; i < 512; ++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); } } }