Core: Still quite buggy map cache
Vicki Pfau vi@endrift.com
Sun, 17 Sep 2017 10:03:30 -0700
3 files changed,
102 insertions(+),
31 deletions(-)
M
include/mgba/core/map-cache.h
→
include/mgba/core/map-cache.h
@@ -11,6 +11,7 @@
CXX_GUARD_START #include <mgba/core/interface.h> +#include <mgba/core/tile-cache.h> DECL_BITFIELD(mMapCacheConfiguration, uint32_t); DECL_BIT(mMapCacheConfiguration, ShouldStore, 0);@@ -28,11 +29,13 @@ DECL_BITS(mMapCacheEntryFlags, PaletteId, 0, 4);
DECL_BIT(mMapCacheEntryFlags, VramClean, 4); DECL_BIT(mMapCacheEntryFlags, HMirror, 5); DECL_BIT(mMapCacheEntryFlags, VMirror, 6); +DECL_BITS(mMapCacheEntryFlags, Mirror, 5, 2); struct mMapCacheEntry { uint32_t vramVersion; uint16_t tileId; mMapCacheEntryFlags flags; + struct mTileCacheEntry tileStatus[16]; }; struct mTileCache;@@ -40,7 +43,6 @@ struct mTileCacheEntry;
struct mMapCache { color_t* cache; struct mTileCache* tileCache; - struct mTileCacheEntry* tileEntries; struct mMapCacheEntry* status; uint8_t* vram;@@ -65,6 +67,8 @@ void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address);
bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y); void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y); + +const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y); CXX_GUARD_END
M
src/core/map-cache.c
→
src/core/map-cache.c
@@ -5,7 +5,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <mgba/core/map-cache.h> -#include <mgba/core/tile-cache.h> #include <mgba-util/memory.h> void mMapCacheInit(struct mMapCache* cache) {@@ -34,12 +33,18 @@ cache->status = anonymousMemoryMap(tiles * sizeof(*cache->status));
} void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config) { + if (config == cache->config) { + return; + } _freeCache(cache); cache->config = config; _redoCacheSize(cache); } void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config) { + if (config == cache->sysConfig) { + return; + } _freeCache(cache); cache->sysConfig = config; _redoCacheSize(cache);@@ -60,37 +65,94 @@ }
void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) { if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) { - address >>= mMapCacheSystemInfoGetMapAlign(cache->sysConfig); - ++cache->status[address].vramVersion; - cache->status[address].flags = mMapCacheEntryFlagsClearVramClean(cache->status[address].flags); + address -= cache->mapStart; + struct mMapCacheEntry* status = &cache->status[address >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig)]; + ++status->vramVersion; + status->flags = mMapCacheEntryFlagsClearVramClean(status->flags); + status->tileStatus[mMapCacheEntryFlagsGetPaletteId(status->flags)].vramClean = 0; } } -bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y) { - size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x; - const struct mMapCacheEntry* status = &cache->status[location]; - return memcmp(status, &entry[location], sizeof(*entry)) == 0; +static inline void _cleanTile(struct mMapCache* cache, const color_t* tile, color_t* mapOut, const struct mMapCacheEntry* status) { + size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); + int x, y; + switch (mMapCacheEntryFlagsGetMirror(status->flags)) { + case 0: + memcpy(mapOut, tile, sizeof(color_t) * 8); + memcpy(&mapOut[stride], &tile[0x08], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(color_t) * 8); + break; + case 1: + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + mapOut[y * stride + (7 - x)] = tile[y * 8 + x]; + } + } + break; + case 2: + memcpy(&mapOut[stride * 7], tile, sizeof(color_t) * 8); + memcpy(&mapOut[stride * 6], &tile[0x08], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 5], &tile[0x10], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 4], &tile[0x18], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 3], &tile[0x20], sizeof(color_t) * 8); + memcpy(&mapOut[stride * 2], &tile[0x28], sizeof(color_t) * 8); + memcpy(&mapOut[stride], &tile[0x30], sizeof(color_t) * 8); + memcpy(mapOut, &tile[0x38], sizeof(color_t) * 8); + break; + case 3: + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + mapOut[(7 - y) * stride + (7 - x)] = tile[y * 8 + x]; + } + } + break; + } } void mMapCacheCleanTile(struct mMapCache* cache, struct mMapCacheEntry* entry, unsigned x, unsigned y) { size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x; struct mMapCacheEntry* status = &cache->status[location]; - status->flags = mMapCacheEntryFlagsFillVramClean(status->flags); - int align = mMapCacheSystemInfoGetMapAlign(cache->sysConfig); - cache->mapParser(cache, status, &cache->vram[(location << align) + cache->mapStart]); + int paletteId = mMapCacheEntryFlagsGetPaletteId(status->flags); + const color_t* tile = NULL; + if (!mMapCacheEntryFlagsIsVramClean(status->flags)) { + status->flags = mMapCacheEntryFlagsFillVramClean(status->flags); + cache->mapParser(cache, status, &cache->vram[cache->mapStart + (location << mMapCacheSystemInfoGetMapAlign(cache->sysConfig))]); + tile = mTileCacheGetTileIfDirty(cache->tileCache, &status->tileStatus[paletteId], status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + if (!tile) { + tile = mTileCacheGetTile(cache->tileCache, status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + } + } else { + tile = mTileCacheGetTileIfDirty(cache->tileCache, &status->tileStatus[paletteId], status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + if (!tile && memcmp(status, &entry[location], sizeof(*entry)) == 0) { + return; + } + tile = mTileCacheGetTile(cache->tileCache, status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + } - int bytesPerPixel = 1 << mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig); - size_t stride = bytesPerPixel * (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)); + size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); color_t* mapOut = &cache->cache[(y * stride + x) * 8]; - const color_t* tile = mTileCacheGetTileIfDirty(cache->tileCache, cache->tileEntries, status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); - memcpy(mapOut, tile, sizeof(color_t) * 8); - memcpy(&mapOut[stride], &tile[0x08], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 2], &tile[0x10], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 3], &tile[0x18], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 4], &tile[0x20], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 5], &tile[0x28], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 6], &tile[0x30], sizeof(color_t) * 8); - memcpy(&mapOut[stride * 7], &tile[0x38], sizeof(color_t) * 8); + _cleanTile(cache, tile, mapOut, status); + entry[location] = *status; +} + +bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y) { + size_t location = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * y + x; + struct mMapCacheEntry* status = &cache->status[location]; + int paletteId = mMapCacheEntryFlagsGetPaletteId(status->flags); + const color_t* tile = NULL; + if (mMapCacheEntryFlagsIsVramClean(status->flags) && memcmp(status, &entry[location], sizeof(*entry)) == 0) { + tile = mTileCacheGetTileIfDirty(cache->tileCache, &status->tileStatus[paletteId], status->tileId + cache->tileStart, mMapCacheEntryFlagsGetPaletteId(status->flags)); + return !tile; + } + return false; +} - entry[location] = *status; +const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y) { + size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig); + return &cache->cache[y * stride]; }
M
src/gba/renderers/cache-set.c
→
src/gba/renderers/cache-set.c
@@ -49,14 +49,19 @@ size_t i;
for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) { mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i])); } + GBAVideoCacheWriteVideoRegister(cache, REG_DISPCNT, video->p->memory.io[REG_DISPCNT >> 1]); + GBAVideoCacheWriteVideoRegister(cache, REG_BG0CNT, video->p->memory.io[REG_BG0CNT >> 1]); + GBAVideoCacheWriteVideoRegister(cache, REG_BG1CNT, video->p->memory.io[REG_BG1CNT >> 1]); + GBAVideoCacheWriteVideoRegister(cache, REG_BG2CNT, video->p->memory.io[REG_BG2CNT >> 1]); + GBAVideoCacheWriteVideoRegister(cache, REG_BG3CNT, video->p->memory.io[REG_BG3CNT >> 1]); } static void mapParser0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) { UNUSED(cache); uint16_t map = *(uint16_t*) vram; entry->tileId = GBA_TEXT_MAP_TILE(map); - entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBA_TEXT_MAP_HFLIP(map)); - entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBA_TEXT_MAP_VFLIP(map)); + entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, !!GBA_TEXT_MAP_HFLIP(map)); + entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, !!GBA_TEXT_MAP_VFLIP(map)); entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map)); }@@ -64,7 +69,7 @@ static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
UNUSED(cache); entry->tileId = *(uint8_t*) vram; entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); - entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags); + entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags); entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags); }@@ -89,8 +94,8 @@ mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2; mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2; - mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); - mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0); mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); break;@@ -100,9 +105,8 @@
static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) { struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg); - int tileStart = GBARegisterBGCNTGetCharBase(value) * 128; + int tileStart = GBARegisterBGCNTGetCharBase(value) * 256; bool p = GBARegisterBGCNTGet256Color(value); - mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11); int size = GBARegisterBGCNTGetSize(value); int tilesWide = 0; int tilesHigh = 0;@@ -134,6 +138,7 @@ }
sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh); sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide); mMapCacheConfigureSystem(map, sysconfig); + mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11); } void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) {