mirror of https://github.com/mgba-emu/mgba.git
Core: Still quite buggy map cache
This commit is contained in:
parent
df9616c15c
commit
c6f0d6c5db
|
@ -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;
|
||||
|
@ -66,6 +68,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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 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 @@ static void _redoCacheSize(struct mMapCache* cache) {
|
|||
}
|
||||
|
||||
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 mMapCacheDeinit(struct mMapCache* cache) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y) {
|
||||
size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
|
||||
return &cache->cache[y * stride];
|
||||
}
|
||||
|
|
|
@ -49,14 +49,19 @@ void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
|
|||
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, vo
|
|||
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 @@ static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
|
|||
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 GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
|
|||
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 @@ static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t
|
|||
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) {
|
||||
|
|
Loading…
Reference in New Issue