GBA Video: Cache mode 0 map data per 8 rows

This commit is contained in:
Vicki Pfau 2017-10-28 00:23:23 -07:00
parent cda0f95464
commit 4e296c3efc
3 changed files with 66 additions and 13 deletions

View File

@ -42,6 +42,8 @@ struct GBAVideoSoftwareBackground {
int16_t dmy;
int32_t sx;
int32_t sy;
int yCache;
uint16_t mapCache[64];
};
enum BlendEffect {

View File

@ -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 @@
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) {

View File

@ -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) {