GBA Video: Cache mode 0 map data per 8 rows
Vicki Pfau vi@endrift.com
Sat, 28 Oct 2017 00:23:23 -0700
3 files changed,
66 insertions(+),
13 deletions(-)
M
include/mgba/internal/gba/renderers/video-software.h
→
include/mgba/internal/gba/renderers/video-software.h
@@ -42,6 +42,8 @@ int16_t dy;
int16_t dmy; int32_t sx; int32_t sy; + int yCache; + uint16_t mapCache[64]; }; enum BlendEffect {
M
src/gba/renderers/software-mode0.c
→
src/gba/renderers/software-mode0.c
@@ -8,17 +8,12 @@
#include <mgba/internal/gba/gba.h> #define BACKGROUND_TEXT_SELECT_CHARACTER \ - localX = tileX * 8 + inX; \ xBase = localX & 0xF8; \ if (background->size & 1) { \ xBase += (localX & 0x100) << 5; \ } \ screenBase = yBase + (xBase >> 3); \ LOAD_16(mapData, screenBase << 1, vram); \ - localY = inY & 0x7; \ - if (GBA_TEXT_MAP_VFLIP(mapData)) { \ - localY = 7 - localY; \ - } #define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_16(BLEND, OBJWIN) \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \@@ -77,11 +72,21 @@ int baseX = x - (mosaicH - mosaicWait); \
if (baseX < 0) { \ int disturbX = (16 + baseX) >> 3; \ inX -= disturbX << 3; \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ baseX -= disturbX << 3; \ inX += disturbX << 3; \ } else { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ if (UNLIKELY(charBase >= 0x10000)) { \@@ -102,8 +107,14 @@ tileData |= tileData << 16; \
carryData = tileData; \ } \ } \ + localX = tileX * 8 + inX; \ for (; length; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ tileData = carryData; \ for (; x < 8 && length; ++x, --length) { \@@ -136,7 +147,12 @@ }
#define DRAW_BACKGROUND_MODE_0_TILES_16(BLEND, OBJWIN) \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \@@ -264,7 +280,12 @@ }
#define DRAW_BACKGROUND_MODE_0_TILES_256(BLEND, OBJWIN) \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ if (UNLIKELY(charBase >= 0x10000)) { \ pixel += 8; \@@ -308,8 +329,14 @@ } \
} #define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \ + localX = tileX * 8 + inX; \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ tileData = carryData; \ for (x = 0; x < 8; ++x) { \@@ -359,8 +386,12 @@ return; \
} \ \ if (inX & 0x7) { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ - \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ int mod8 = inX & 0x7; \ int end = outX + 0x8 - mod8; \ if (end > renderer->end) { \@@ -390,10 +421,15 @@ /*!*/ if (VIDEO_CHECKS && UNLIKELY(outX > VIDEO_HORIZONTAL_PIXELS)) { \
/*!*/ mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw would occur!"); \ /*!*/ return; \ /*!*/ } \ + localX = (tileX * 8 + inX) & 0x1FF; \ DRAW_BACKGROUND_MODE_0_TILES_ ## BPP (BLEND, OBJWIN) \ if (length & 0x7) { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ - \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ int mod8 = length & 0x7; \ if (VIDEO_CHECKS && UNLIKELY(outX + mod8 != renderer->end)) { \ mLOG(GBA_VIDEO, FATAL, "Invariant doesn't hold in background draw!"); \@@ -410,7 +446,7 @@ return; \
} void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) { - int inX = renderer->start + background->x; + int inX = (renderer->start + background->x) & 0x1FF; int length = renderer->end - renderer->start; if (background->mosaic) { int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1;@@ -458,10 +494,20 @@ uint32_t tileData;
uint32_t current; int pixelData; int paletteData; - int tileX = 0; + int tileX; int tileEnd = ((length + inX) >> 3) - (inX >> 3); uint16_t* vram = renderer->d.vram; + if (background->yCache != inY >> 3) { + localX = 0; + for (tileX = 0; tileX < 64; ++tileX, localX += 8) { + BACKGROUND_TEXT_SELECT_CHARACTER; + background->mapCache[tileX] = mapData; + } + background->yCache = inY >> 3; + } + + tileX = 0; if (!objwinSlowPath) { if (!(flags & FLAG_TARGET_2)) { if (!background->multipalette) {
M
src/gba/renderers/video-software.c
→
src/gba/renderers/video-software.c
@@ -140,6 +140,7 @@ bg->dy = 0;
bg->dmy = 256; bg->sx = 0; bg->sy = 0; + bg->yCache = -1; } }@@ -388,6 +389,10 @@ if (renderer->cache) {
mCacheSetWriteVRAM(renderer->cache, address); } memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty)); + softwareRenderer->bg[0].yCache = -1; + softwareRenderer->bg[1].yCache = -1; + softwareRenderer->bg[2].yCache = -1; + softwareRenderer->bg[3].yCache = -1; } static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam) {