From 4e296c3efc2fb1b753ef1a1085642d691d4b1567 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 28 Oct 2017 00:23:23 -0700 Subject: [PATCH] GBA Video: Cache mode 0 map data per 8 rows --- .../internal/gba/renderers/video-software.h | 2 + src/gba/renderers/software-mode0.c | 72 +++++++++++++++---- src/gba/renderers/video-software.c | 5 ++ 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h index 6ce9c2037..77aaf63fb 100644 --- a/include/mgba/internal/gba/renderers/video-software.h +++ b/include/mgba/internal/gba/renderers/video-software.h @@ -42,6 +42,8 @@ struct GBAVideoSoftwareBackground { int16_t dmy; int32_t sx; int32_t sy; + int yCache; + uint16_t mapCache[64]; }; enum BlendEffect { diff --git a/src/gba/renderers/software-mode0.c b/src/gba/renderers/software-mode0.c index 74db03180..f0925528a 100644 --- a/src/gba/renderers/software-mode0.c +++ b/src/gba/renderers/software-mode0.c @@ -8,17 +8,12 @@ #include #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 @@ 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 @@ 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 @@ } \ \ 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 @@ /*!*/ 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 @@ } 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 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer 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) { diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index f1148bc0f..04431cfe5 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -140,6 +140,7 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) { bg->dmy = 256; bg->sx = 0; bg->sy = 0; + bg->yCache = -1; } } @@ -388,6 +389,10 @@ static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, 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) {