mirror of https://github.com/mgba-emu/mgba.git
DS Video: OBJ extended palettes
This commit is contained in:
parent
cf5d6709fe
commit
e4795c5d86
|
@ -32,6 +32,10 @@ struct DSVideoSoftwareRenderer {
|
|||
color_t extPaletteB[16384];
|
||||
color_t variantPaletteA[16384];
|
||||
color_t variantPaletteB[16384];
|
||||
color_t objExtPaletteA[4096];
|
||||
color_t objExtPaletteB[4096];
|
||||
color_t objVariantPaletteA[4096];
|
||||
color_t objVariantPaletteB[4096];
|
||||
};
|
||||
|
||||
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer);
|
||||
|
|
|
@ -86,11 +86,11 @@ struct DSVideoRenderer {
|
|||
uint16_t* vramABG[32];
|
||||
uint16_t* vramAOBJ[32];
|
||||
uint16_t* vramABGExtPal[4];
|
||||
uint16_t* vramAOBJExtPal[4];
|
||||
uint16_t* vramAOBJExtPal;
|
||||
uint16_t* vramBBG[32];
|
||||
uint16_t* vramBOBJ[32];
|
||||
uint16_t* vramBBGExtPal[4];
|
||||
uint16_t* vramBOBJExtPal[4];
|
||||
uint16_t* vramBOBJExtPal;
|
||||
union DSOAM* oam;
|
||||
};
|
||||
|
||||
|
@ -109,11 +109,11 @@ struct DSVideo {
|
|||
uint16_t* vramABG[32];
|
||||
uint16_t* vramAOBJ[32];
|
||||
uint16_t* vramABGExtPal[4];
|
||||
uint16_t* vramAOBJExtPal[4];
|
||||
uint16_t* vramAOBJExtPal;
|
||||
uint16_t* vramBBG[32];
|
||||
uint16_t* vramBOBJ[32];
|
||||
uint16_t* vramBBGExtPal[4];
|
||||
uint16_t* vramBOBJExtPal[4];
|
||||
uint16_t* vramBOBJExtPal;
|
||||
union DSOAM oam;
|
||||
|
||||
int32_t frameCounter;
|
||||
|
|
|
@ -132,6 +132,8 @@ struct GBAVideoSoftwareRenderer {
|
|||
enum BlendEffect blendEffect;
|
||||
color_t normalPalette[512];
|
||||
color_t variantPalette[512];
|
||||
color_t* objExtPalette;
|
||||
color_t* objExtVariantPalette;
|
||||
|
||||
uint16_t blda;
|
||||
uint16_t bldb;
|
||||
|
|
|
@ -21,21 +21,35 @@ static void DSVideoSoftwareRendererFinishFrame(struct DSVideoRenderer* renderer)
|
|||
static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, size_t* stride, const void** pixels);
|
||||
static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
|
||||
|
||||
static bool _regenerateExtPalette(struct DSVideoSoftwareRenderer* renderer, bool engB, int slot) {
|
||||
static bool _regenerateExtPalette(struct DSVideoSoftwareRenderer* renderer, bool obj, bool engB, int slot) {
|
||||
color_t* palette;
|
||||
color_t* variantPalette;
|
||||
struct GBAVideoSoftwareRenderer* softwareRenderer;
|
||||
uint16_t* vram;
|
||||
if (!engB) {
|
||||
palette = &renderer->extPaletteA[slot * 4096];
|
||||
variantPalette = &renderer->variantPaletteA[slot * 4096];
|
||||
softwareRenderer = &renderer->engA;
|
||||
vram = renderer->d.vramABGExtPal[slot];
|
||||
if (!obj) {
|
||||
if (!engB) {
|
||||
palette = &renderer->extPaletteA[slot * 4096];
|
||||
variantPalette = &renderer->variantPaletteA[slot * 4096];
|
||||
softwareRenderer = &renderer->engA;
|
||||
vram = renderer->d.vramABGExtPal[slot];
|
||||
} else {
|
||||
palette = &renderer->extPaletteB[slot * 4096];
|
||||
variantPalette = &renderer->variantPaletteB[slot * 4096];
|
||||
softwareRenderer = &renderer->engB;
|
||||
vram = renderer->d.vramBBGExtPal[slot];
|
||||
}
|
||||
} else {
|
||||
palette = &renderer->extPaletteB[slot * 4096];
|
||||
variantPalette = &renderer->variantPaletteB[slot * 4096];
|
||||
softwareRenderer = &renderer->engB;
|
||||
vram = renderer->d.vramBBGExtPal[slot];
|
||||
if (!engB) {
|
||||
palette = renderer->objExtPaletteA;
|
||||
variantPalette = renderer->variantPaletteA;
|
||||
softwareRenderer = &renderer->engA;
|
||||
vram = renderer->d.vramAOBJExtPal;
|
||||
} else {
|
||||
palette = renderer->objExtPaletteB;
|
||||
variantPalette = renderer->variantPaletteB;
|
||||
softwareRenderer = &renderer->engB;
|
||||
vram = renderer->d.vramBOBJExtPal;
|
||||
}
|
||||
}
|
||||
if (!vram) {
|
||||
return false;
|
||||
|
@ -154,7 +168,7 @@ static void DSVideoSoftwareRendererUpdateDISPCNT(struct DSVideoSoftwareRenderer*
|
|||
if (i < 2 && GBARegisterBGCNTIsExtPaletteSlot(eng->bg[i].control)) {
|
||||
slot += 2;
|
||||
}
|
||||
if (eng->bg[i].extPalette != &extPalette[slot * 4096] && _regenerateExtPalette(softwareRenderer, engB, slot)) {
|
||||
if (eng->bg[i].extPalette != &extPalette[slot * 4096] && _regenerateExtPalette(softwareRenderer, false, engB, slot)) {
|
||||
eng->bg[i].extPalette = &extPalette[slot * 4096];
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +178,19 @@ static void DSVideoSoftwareRendererUpdateDISPCNT(struct DSVideoSoftwareRenderer*
|
|||
eng->bg[2].extPalette = NULL;
|
||||
eng->bg[3].extPalette = NULL;
|
||||
}
|
||||
if (DSRegisterDISPCNTIsObjExtPalette(dispcnt)) {
|
||||
if (!engB) {
|
||||
softwareRenderer->engA.objExtPalette = softwareRenderer->objExtPaletteA;
|
||||
} else {
|
||||
softwareRenderer->engB.objExtPalette = softwareRenderer->objExtPaletteB;
|
||||
}
|
||||
} else {
|
||||
if (!engB) {
|
||||
softwareRenderer->engA.objExtPalette = NULL;
|
||||
} else {
|
||||
softwareRenderer->engB.objExtPalette = NULL;
|
||||
}
|
||||
}
|
||||
if (!engB) {
|
||||
uint32_t charBase = DSRegisterDISPCNTGetCharBase(softwareRenderer->dispcntA) << 16;
|
||||
uint32_t screenBase = DSRegisterDISPCNTGetScreenBase(softwareRenderer->dispcntA) << 16;
|
||||
|
@ -251,7 +278,7 @@ static void DSVideoSoftwareRendererWriteOAM(struct DSVideoRenderer* renderer, ui
|
|||
|
||||
static void DSVideoSoftwareRendererInvalidateExtPal(struct DSVideoRenderer* renderer, bool obj, bool engB, int slot) {
|
||||
struct DSVideoSoftwareRenderer* softwareRenderer = (struct DSVideoSoftwareRenderer*) renderer;
|
||||
_regenerateExtPalette(softwareRenderer, engB, slot);
|
||||
_regenerateExtPalette(softwareRenderer, obj, engB, slot);
|
||||
}
|
||||
|
||||
static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* renderer, int y) {
|
||||
|
|
|
@ -195,11 +195,11 @@ void DSVideoAssociateRenderer(struct DSVideo* video, struct DSVideoRenderer* ren
|
|||
memcpy(renderer->vramABG, video->vramABG, sizeof(renderer->vramABG));
|
||||
memcpy(renderer->vramAOBJ, video->vramAOBJ, sizeof(renderer->vramAOBJ));
|
||||
memcpy(renderer->vramABGExtPal, video->vramABGExtPal, sizeof(renderer->vramABGExtPal));
|
||||
memcpy(renderer->vramAOBJExtPal, video->vramAOBJExtPal, sizeof(renderer->vramAOBJExtPal));
|
||||
renderer->vramAOBJExtPal = video->vramAOBJExtPal;
|
||||
memcpy(renderer->vramBBG, video->vramBBG, sizeof(renderer->vramBBG));
|
||||
memcpy(renderer->vramBOBJ, video->vramBOBJ, sizeof(renderer->vramBOBJ));
|
||||
memcpy(renderer->vramBBGExtPal, video->vramBBGExtPal, sizeof(renderer->vramBBGExtPal));
|
||||
memcpy(renderer->vramBOBJExtPal, video->vramBOBJExtPal, sizeof(renderer->vramBOBJExtPal));
|
||||
renderer->vramBOBJExtPal = video->vramBOBJExtPal;
|
||||
renderer->oam = &video->oam;
|
||||
video->renderer->init(video->renderer);
|
||||
}
|
||||
|
@ -395,6 +395,20 @@ void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldVa
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MODE_A_OBJ_EXT_PAL:
|
||||
if (ds->video.vramAOBJExtPal == memory->vramBank[index]) {
|
||||
ds->video.vramAOBJExtPal = NULL;
|
||||
ds->video.renderer->vramAOBJExtPal = NULL;
|
||||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, false, 0);
|
||||
}
|
||||
break;
|
||||
case MODE_B_OBJ_EXT_PAL:
|
||||
if (ds->video.vramBOBJExtPal == memory->vramBank[index]) {
|
||||
ds->video.vramBOBJExtPal = NULL;
|
||||
ds->video.renderer->vramBOBJExtPal = NULL;
|
||||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, true, 0);
|
||||
}
|
||||
break;
|
||||
case MODE_7_VRAM:
|
||||
for (i = 0; i < size; i += 16) {
|
||||
ds->memory.vram7[(offset + i) >> 4] = NULL;
|
||||
|
@ -458,6 +472,16 @@ void DSVideoConfigureVRAM(struct DS* ds, int index, uint8_t value, uint8_t oldVa
|
|||
ds->video.renderer->invalidateExtPal(ds->video.renderer, false, true, offset + i);
|
||||
}
|
||||
break;
|
||||
case MODE_A_OBJ_EXT_PAL:
|
||||
ds->video.vramAOBJExtPal = memory->vramBank[index];
|
||||
ds->video.renderer->vramAOBJExtPal = ds->video.vramAOBJExtPal;
|
||||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, false, 0);
|
||||
break;
|
||||
case MODE_B_OBJ_EXT_PAL:
|
||||
ds->video.vramBOBJExtPal = memory->vramBank[index];
|
||||
ds->video.renderer->vramBOBJExtPal = ds->video.vramBOBJExtPal;
|
||||
ds->video.renderer->invalidateExtPal(ds->video.renderer, true, true, 0);
|
||||
break;
|
||||
case MODE_7_VRAM:
|
||||
for (i = 0; i < size; i += 16) {
|
||||
ds->memory.vram7[(offset + i) >> 4] = &memory->vramBank[index][i << (DS_VRAM_OFFSET - 5)];
|
||||
|
|
|
@ -364,7 +364,7 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256Ext(BLEND, OBJWIN) \
|
||||
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256EXT(BLEND, OBJWIN) \
|
||||
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||
palette = &mainPalette[paletteData]; \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||
|
@ -414,7 +414,7 @@
|
|||
pixel = &renderer->row[outX]; \
|
||||
}
|
||||
|
||||
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256Ext(BLEND, OBJWIN) \
|
||||
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256EXT(BLEND, OBJWIN) \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||
vram = renderer->d.vramBG[charBase >> VRAM_BLOCK_OFFSET]; \
|
||||
if (UNLIKELY(!vram)) { \
|
||||
|
@ -463,7 +463,7 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define DRAW_BACKGROUND_MODE_0_TILES_256Ext(BLEND, OBJWIN) \
|
||||
#define DRAW_BACKGROUND_MODE_0_TILES_256EXT(BLEND, OBJWIN) \
|
||||
for (; tileX < tileEnd; ++tileX) { \
|
||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 8; \
|
||||
|
@ -511,7 +511,7 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256Ext(BLEND, OBJWIN) \
|
||||
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256EXT(BLEND, OBJWIN) \
|
||||
for (; tileX < tileEnd; ++tileX) { \
|
||||
BACKGROUND_TEXT_SELECT_CHARACTER; \
|
||||
charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
|
||||
|
@ -685,7 +685,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
|||
} else if (!background->extPalette) {
|
||||
DRAW_BACKGROUND_MODE_0(256, NoBlend, NO_OBJWIN);
|
||||
} else {
|
||||
DRAW_BACKGROUND_MODE_0(256Ext, NoBlend, NO_OBJWIN);
|
||||
DRAW_BACKGROUND_MODE_0(256EXT, NoBlend, NO_OBJWIN);
|
||||
}
|
||||
} else {
|
||||
if (!background->multipalette) {
|
||||
|
@ -693,7 +693,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
|||
} else if (!background->extPalette) {
|
||||
DRAW_BACKGROUND_MODE_0(256, Blend, NO_OBJWIN);
|
||||
} else {
|
||||
DRAW_BACKGROUND_MODE_0(256Ext, Blend, NO_OBJWIN);
|
||||
DRAW_BACKGROUND_MODE_0(256EXT, Blend, NO_OBJWIN);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -703,7 +703,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
|||
} else if (!background->extPalette) {
|
||||
DRAW_BACKGROUND_MODE_0(256, NoBlend, OBJWIN);
|
||||
} else {
|
||||
DRAW_BACKGROUND_MODE_0(256Ext, NoBlend, OBJWIN);
|
||||
DRAW_BACKGROUND_MODE_0(256EXT, NoBlend, OBJWIN);
|
||||
}
|
||||
} else {
|
||||
if (!background->multipalette) {
|
||||
|
@ -711,7 +711,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer
|
|||
} else if (!background->extPalette) {
|
||||
DRAW_BACKGROUND_MODE_0(256, Blend, OBJWIN);
|
||||
} else {
|
||||
DRAW_BACKGROUND_MODE_0(256Ext, Blend, OBJWIN);
|
||||
DRAW_BACKGROUND_MODE_0(256EXT, Blend, OBJWIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
|||
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
|
||||
x >>= 23;
|
||||
unsigned charBase = GBAObjAttributesCGetTile(sprite->c) * renderer->tileStride;
|
||||
if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) {
|
||||
if (!renderer->d.vramOBJ[charBase >> VRAM_BLOCK_OFFSET]) {
|
||||
return 0;
|
||||
}
|
||||
if (renderer->spriteCyclesRemaining <= 0) {
|
||||
|
@ -202,7 +202,9 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
|||
color_t* objwinPalette = palette;
|
||||
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed);
|
||||
|
||||
if (variant) {
|
||||
if (GBAObjAttributesAIs256Color(sprite->a) && renderer->objExtPalette) {
|
||||
palette = renderer->objExtPalette;
|
||||
} else if (variant) {
|
||||
palette = &renderer->variantPalette[0x100];
|
||||
if (GBAWindowControlIsBlendEnable(renderer->objwin.packed)) {
|
||||
objwinPalette = palette;
|
||||
|
|
|
@ -100,6 +100,8 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
|||
LOAD_16(entry, i, softwareRenderer->d.palette);
|
||||
GBAVideoSoftwareRendererWritePalette(renderer, i, entry);
|
||||
}
|
||||
softwareRenderer->objExtPalette = NULL;
|
||||
softwareRenderer->objExtVariantPalette = NULL;
|
||||
_updatePalettes(softwareRenderer);
|
||||
|
||||
softwareRenderer->blda = 0;
|
||||
|
@ -497,8 +499,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
|
|||
return;
|
||||
}
|
||||
|
||||
uint16_t* objVramBase = softwareRenderer->d.vramOBJ[0];
|
||||
if (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) >= 3) {
|
||||
softwareRenderer->d.vramOBJ[0] = NULL; // OBJ VRAM bottom is blocked in bitmap modes
|
||||
}
|
||||
|
||||
GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer, y);
|
||||
int spriteLayers = GBAVideoSoftwareRendererPreprocessSpriteLayer(softwareRenderer, y);
|
||||
softwareRenderer->d.vramOBJ[0] = objVramBase;
|
||||
|
||||
int w;
|
||||
unsigned priority;
|
||||
|
|
Loading…
Reference in New Issue