GBA Video: Implement mosaic for modes 2 - 5, untested with windows
Jeffrey Pfau jeffrey@endrift.com
Sat, 15 Nov 2014 01:32:58 -0800
1 files changed,
62 insertions(+),
32 deletions(-)
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -1249,9 +1249,17 @@ }
} #define BACKGROUND_BITMAP_INIT \ - UNUSED(unused); \ int32_t x = background->sx + (renderer->start - 1) * background->dx; \ int32_t y = background->sy + (renderer->start - 1) * background->dy; \ + int mosaicH = 0; \ + int mosaicWait = 0; \ + if (background->mosaic) { \ + int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; \ + y -= (inY % mosaicV) * background->dmy; \ + x -= (inY % mosaicV) * background->dmx; \ + mosaicH = GBAMosaicControlGetBgH(renderer->mosaic); \ + mosaicWait = renderer->start % (mosaicH + 1); \ + } \ int32_t localX; \ int32_t localY; \ \@@ -1279,7 +1287,7 @@ localX = x; \
localY = y; \ } -static void _drawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int unused) { +static void _drawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) { int sizeAdjusted = 0x8000 << background->size; BACKGROUND_BITMAP_INIT;@@ -1287,7 +1295,7 @@
uint32_t screenBase = background->screenBase; uint32_t charBase = background->charBase; uint8_t mapData; - uint8_t tileData; + uint8_t tileData = 0; int outX; uint32_t* pixel;@@ -1295,17 +1303,23 @@ for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
x += background->dx; y += background->dy; - if (background->overflow) { - localX = x & (sizeAdjusted - 1); - localY = y & (sizeAdjusted - 1); - } else if ((x | y) & ~(sizeAdjusted - 1)) { - continue; + if (!mosaicWait) { + if (background->overflow) { + localX = x & (sizeAdjusted - 1); + localY = y & (sizeAdjusted - 1); + } else if ((x | y) & ~(sizeAdjusted - 1)) { + continue; + } else { + localX = x; + localY = y; + } + mapData = ((uint8_t*)renderer->d.vram)[screenBase + (localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; + tileData = ((uint8_t*)renderer->d.vram)[charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; + + mosaicWait = mosaicH; } else { - localX = x; - localY = y; + --mosaicWait; } - mapData = ((uint8_t*)renderer->d.vram)[screenBase + (localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; - tileData = ((uint8_t*)renderer->d.vram)[charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; uint32_t current = *pixel; if (tileData && IS_WRITABLE(current)) {@@ -1319,25 +1333,30 @@ }
} } -static void _drawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int unused) { +static void _drawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) { BACKGROUND_BITMAP_INIT; - uint32_t color; + uint32_t color = renderer->normalPalette[0]; int outX; uint32_t* pixel; for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); - LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vram); + if (!mosaicWait) { + LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vram); #ifndef COLOR_16_BIT - unsigned color32; - color32 = 0; - color32 |= (color << 3) & 0xF8; - color32 |= (color << 6) & 0xF800; - color32 |= (color << 9) & 0xF80000; - color = color32; + unsigned color32; + color32 = 0; + color32 |= (color << 3) & 0xF8; + color32 |= (color << 6) & 0xF800; + color32 |= (color << 9) & 0xF80000; + color = color32; #endif + mosaicWait = mosaicH; + } else { + --mosaicWait; + } uint32_t current = *pixel; if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {@@ -1352,10 +1371,10 @@ }
} } -static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int unused) { +static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) { BACKGROUND_BITMAP_INIT; - uint16_t color; + uint16_t color = renderer->normalPalette[0]; uint32_t offset = 0; if (GBARegisterDISPCNTIsFrameSelect(renderer->dispcnt)) { offset = 0xA000;@@ -1366,7 +1385,13 @@ uint32_t* pixel;
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); - color = ((uint8_t*)renderer->d.vram)[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS]; + if (!mosaicWait) { + color = ((uint8_t*)renderer->d.vram)[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS]; + + mosaicWait = mosaicH; + } else { + --mosaicWait; + } uint32_t current = *pixel; if (color && IS_WRITABLE(current)) {@@ -1380,10 +1405,10 @@ }
} } -static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int unused) { +static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) { BACKGROUND_BITMAP_INIT; - uint32_t color; + uint32_t color = renderer->normalPalette[0]; uint32_t offset = 0; if (GBARegisterDISPCNTIsFrameSelect(renderer->dispcnt)) { offset = 0xA000;@@ -1394,14 +1419,19 @@ uint32_t* pixel;
for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { BACKGROUND_BITMAP_ITERATE(160, 128); - LOAD_16(color, (offset + (localX >> 8) + (localY >> 8) * 160) << 1, renderer->d.vram); + if (!mosaicWait) { + LOAD_16(color, (offset + (localX >> 8) + (localY >> 8) * 160) << 1, renderer->d.vram); #ifndef COLOR_16_BIT - unsigned color32 = 0; - color32 |= (color << 9) & 0xF80000; - color32 |= (color << 3) & 0xF8; - color32 |= (color << 6) & 0xF800; - color = color32; + unsigned color32 = 0; + color32 |= (color << 9) & 0xF80000; + color32 |= (color << 3) & 0xF8; + color32 |= (color << 6) & 0xF800; + color = color32; #endif + mosaicWait = mosaicH; + } else { + --mosaicWait; + } uint32_t current = *pixel; if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {