DS Video: OBJ extended palettes

This commit is contained in:
Vicki Pfau 2017-02-26 16:43:03 -08:00
parent cf5d6709fe
commit e4795c5d86
8 changed files with 95 additions and 28 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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)];

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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;