mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Support highlighting layers
This commit is contained in:
parent
570f2c5f38
commit
f41f3a8478
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue