DS Video: Initial implementation of extended graphics modes 1.0 and 1.1

This commit is contained in:
Vicki Pfau 2017-03-13 12:14:31 -07:00
parent 62b5ca0aa8
commit b73125e4a2
1 changed files with 128 additions and 3 deletions

View File

@ -24,6 +24,8 @@ static void DSVideoSoftwareRendererGetPixels(struct DSVideoRenderer* renderer, s
static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels); static void DSVideoSoftwareRendererPutPixels(struct DSVideoRenderer* renderer, size_t stride, const void* pixels);
static void DSVideoSoftwareRendererDrawBackgroundExt0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY); static void DSVideoSoftwareRendererDrawBackgroundExt0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY);
static void DSVideoSoftwareRendererDrawBackgroundExt1(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY);
static void DSVideoSoftwareRendererDrawBackgroundExt2(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY);
static bool _regenerateExtPalette(struct DSVideoSoftwareRenderer* renderer, bool obj, bool engB, int slot) { static bool _regenerateExtPalette(struct DSVideoSoftwareRenderer* renderer, bool obj, bool engB, int slot) {
color_t* palette; color_t* palette;
@ -130,7 +132,6 @@ static void _updateCharBase(struct DSVideoSoftwareRenderer* softwareRenderer, bo
} }
} }
void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) { void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) {
renderer->d.init = DSVideoSoftwareRendererInit; renderer->d.init = DSVideoSoftwareRendererInit;
renderer->d.reset = DSVideoSoftwareRendererReset; renderer->d.reset = DSVideoSoftwareRendererReset;
@ -429,8 +430,10 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend
case 5: case 5:
if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[2].control)) { if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[2].control)) {
DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[2], y); DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[2], y);
} else if (!GBARegisterBGCNTIsExtendedMode0(softwareRenderer->bg[2].control)) {
DSVideoSoftwareRendererDrawBackgroundExt1(softwareRenderer, &softwareRenderer->bg[2], y);
} else { } else {
// TODO DSVideoSoftwareRendererDrawBackgroundExt2(softwareRenderer, &softwareRenderer->bg[2], y);
} }
break; break;
} }
@ -449,8 +452,10 @@ static void DSVideoSoftwareRendererDrawGBAScanline(struct GBAVideoRenderer* rend
case 5: case 5:
if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[3].control)) { if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[3].control)) {
DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[3], y); DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[3], y);
} else if (!GBARegisterBGCNTIsExtendedMode0(softwareRenderer->bg[3].control)) {
DSVideoSoftwareRendererDrawBackgroundExt1(softwareRenderer, &softwareRenderer->bg[3], y);
} else { } else {
// TODO DSVideoSoftwareRendererDrawBackgroundExt2(softwareRenderer, &softwareRenderer->bg[3], y);
} }
break; break;
} }
@ -716,3 +721,123 @@ void DSVideoSoftwareRendererDrawBackgroundExt0(struct GBAVideoSoftwareRenderer*
} }
} }
} }
void DSVideoSoftwareRendererDrawBackgroundExt1(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
BACKGROUND_BITMAP_INIT;
uint8_t color;
int width, height;
switch (background->size) {
case 0:
width = 128;
height = 128;
break;
case 1:
width = 256;
height = 256;
break;
case 2:
width = 512;
height = 256;
break;
case 3:
width = 512;
height = 512;
break;
}
int outX;
for (outX = renderer->start; outX < renderer->end; ++outX) {
BACKGROUND_BITMAP_ITERATE(width, height);
if (!mosaicWait) {
uint32_t address = (localX >> 8) + (localY >> 8) * width;
color = ((uint8_t*)renderer->d.vramBG[address >> 17])[address];
mosaicWait = mosaicH;
} else {
--mosaicWait;
}
uint32_t current = renderer->row[outX];
if (color && IS_WRITABLE(current)) {
if (!objwinSlowPath) {
_compositeBlendNoObjwin(renderer, outX, palette[color] | flags, current);
} else if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) {
color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette;
unsigned mergedFlags = flags;
if (current & FLAG_OBJWIN) {
mergedFlags = objwinFlags;
}
_compositeBlendObjwin(renderer, outX, currentPalette[color] | mergedFlags, current);
}
}
}
}
void DSVideoSoftwareRendererDrawBackgroundExt2(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
BACKGROUND_BITMAP_INIT;
uint32_t color;
int width, height;
switch (background->size) {
case 0:
width = 128;
height = 128;
break;
case 1:
width = 256;
height = 256;
break;
case 2:
width = 512;
height = 256;
break;
case 3:
width = 512;
height = 512;
break;
}
int outX;
for (outX = renderer->start; outX < renderer->end; ++outX) {
BACKGROUND_BITMAP_ITERATE(width, height);
if (!mosaicWait) {
uint32_t address = ((localX >> 8) + (localY >> 8) * width) << 1;
LOAD_16(color, address & 0x1FFFE, renderer->d.vramBG[address >> 17]);
#ifndef COLOR_16_BIT
unsigned color32;
color32 = 0;
color32 |= (color << 3) & 0xF8;
color32 |= (color << 6) & 0xF800;
color32 |= (color << 9) & 0xF80000;
color32 |= (color32 >> 5) & 0x070707;
color = color32;
#elif COLOR_5_6_5
uint16_t color16 = 0;
color16 |= (color & 0x001F) << 11;
color16 |= (color & 0x03E0) << 1;
color16 |= (color & 0x7C00) >> 10;
color = color16;
#endif
mosaicWait = mosaicH;
} else {
--mosaicWait;
}
uint32_t current = renderer->row[outX];
if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != objwinOnly) {
unsigned mergedFlags = flags;
if (current & FLAG_OBJWIN) {
mergedFlags = objwinFlags;
}
if (!variant) {
_compositeBlendObjwin(renderer, outX, color | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
_compositeBlendObjwin(renderer, outX, _brighten(color, renderer->bldy) | mergedFlags, current);
} else if (renderer->blendEffect == BLEND_DARKEN) {
_compositeBlendObjwin(renderer, outX, _darken(color, renderer->bldy) | mergedFlags, current);
}
}
}
}