DS Video: OBJ extended palettes
@@ -32,6 +32,10 @@ color_t extPaletteA[16384];
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 @@ uint16_t* vram;
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 @@ uint16_t* vram;
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 @@ unsigned target2Bd;
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 @@ int slot = i;
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]; } }@@ -163,6 +177,19 @@ eng->bg[0].extPalette = NULL;
eng->bg[1].extPalette = NULL; 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;@@ -251,7 +278,7 @@ }
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 @@ renderer->vram = video->vram;
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 @@ ds->video.renderer->invalidateExtPal(ds->video.renderer, false, true, offset + i);
} } 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;@@ -457,6 +471,16 @@ ds->video.vramBBGExtPal[offset + i] = &memory->vramBank[index][i << 12];
ds->video.renderer->vramBBGExtPal[offset + i] = ds->video.vramBBGExtPal[offset + i]; 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) {
@@ -364,7 +364,7 @@ ++pixel; \
} \ } -#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 @@ outX = end; \
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 @@ pixel = &renderer->row[outX]; \
} \ } -#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 @@ pixel += 4; \
} \ } -#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 @@ DRAW_BACKGROUND_MODE_0(16, NoBlend, NO_OBJWIN);
} 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 @@ DRAW_BACKGROUND_MODE_0(16, Blend, NO_OBJWIN);
} 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 @@ DRAW_BACKGROUND_MODE_0(16, NoBlend, OBJWIN);
} 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 @@ DRAW_BACKGROUND_MODE_0(16, Blend, OBJWIN);
} 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 @@ }
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 @@ color_t* palette = &renderer->normalPalette[0x100];
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 @@ uint16_t entry;
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 @@ }
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;