all repos — mgba @ b73125e4a2489a6dbc0536fb3933b39ac5448f71

mGBA Game Boy Advance Emulator

DS Video: Initial implementation of extended graphics modes 1.0 and 1.1
Vicki Pfau vi@endrift.com
Mon, 13 Mar 2017 12:14:31 -0700
commit

b73125e4a2489a6dbc0536fb3933b39ac5448f71

parent

62b5ca0aa8384e278100139b56a991dc5212ff12

1 files changed, 128 insertions(+), 3 deletions(-)

jump to
M src/ds/renderers/software.csrc/ds/renderers/software.c

@@ -24,6 +24,8 @@ 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 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) { color_t* palette;

@@ -129,7 +131,6 @@ softwareRenderer->engA.bg[i].screenBase |= screenBase;

} } } - void DSVideoSoftwareRendererCreate(struct DSVideoSoftwareRenderer* renderer) { renderer->d.init = DSVideoSoftwareRendererInit;

@@ -429,8 +430,10 @@ break;

case 5: if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[2].control)) { DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[2], y); + } else if (!GBARegisterBGCNTIsExtendedMode0(softwareRenderer->bg[2].control)) { + DSVideoSoftwareRendererDrawBackgroundExt1(softwareRenderer, &softwareRenderer->bg[2], y); } else { - // TODO + DSVideoSoftwareRendererDrawBackgroundExt2(softwareRenderer, &softwareRenderer->bg[2], y); } break; }

@@ -449,8 +452,10 @@ case 4:

case 5: if (!GBARegisterBGCNTIsExtendedMode1(softwareRenderer->bg[3].control)) { DSVideoSoftwareRendererDrawBackgroundExt0(softwareRenderer, &softwareRenderer->bg[3], y); + } else if (!GBARegisterBGCNTIsExtendedMode0(softwareRenderer->bg[3].control)) { + DSVideoSoftwareRendererDrawBackgroundExt1(softwareRenderer, &softwareRenderer->bg[3], y); } else { - // TODO + DSVideoSoftwareRendererDrawBackgroundExt2(softwareRenderer, &softwareRenderer->bg[3], y); } break; }

@@ -716,3 +721,123 @@ DRAW_BACKGROUND_EXT_0(Blend, OBJWIN);

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