GBA Video: Allow multiple handles into the same tile cache
Jeffrey Pfau jeffrey@endrift.com
Sun, 16 Oct 2016 18:23:28 -0700
7 files changed,
81 insertions(+),
43 deletions(-)
M
src/gba/renderers/tile-cache.c
→
src/gba/renderers/tile-cache.c
@@ -46,6 +46,7 @@
void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address) { size_t i; for (i = 0; i < 16; ++i) { + ++cache->status[address >> 5][i].vramVersion; cache->status[address >> 5][i].vramClean = 0; } }@@ -136,19 +137,22 @@ }
return tile; } -const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { +const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, GBAVideoTileCacheStatus handle, unsigned tileId, unsigned paletteId) { struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId & 0xF]; + uint16_t* tile = NULL; if (!status->vramClean || status->palette256 || status->paletteVersion != cache->globalPaletteVersion[paletteId]) { - uint16_t* tile = _tileLookup(cache, tileId, paletteId); + tile = _tileLookup(cache, tileId, paletteId); _regenerateTile16(cache, tile, tileId, paletteId); status->paletteVersion = cache->globalPaletteVersion[paletteId]; status->palette256 = 0; status->vramClean = 1; - return tile; + } + if (memcmp(status, &handle[tileId][paletteId & 0xF], sizeof(*status))) { + tile = _tileLookup(cache, tileId, paletteId); + handle[tileId][paletteId & 0xF] = *status; } - return NULL; + return tile; } - const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId];@@ -162,15 +166,19 @@ }
return tile; } -const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { +const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, GBAVideoTileCacheStatus handle, unsigned tileId, unsigned paletteId) { struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId]; + uint16_t* tile = NULL; if (!status->vramClean || !status->palette256 || status->paletteVersion != cache->globalPalette256Version[paletteId]) { - uint16_t* tile = _tileLookup(cache, tileId, paletteId); + tile = _tileLookup(cache, tileId, paletteId); _regenerateTile256(cache, tile, tileId, paletteId); status->paletteVersion = cache->globalPalette256Version[paletteId]; status->palette256 = 1; status->vramClean = 1; - return tile; } - return NULL; + if (memcmp(status, &handle[tileId][paletteId], sizeof(*status))) { + tile = _tileLookup(cache, tileId, paletteId); + handle[tileId][paletteId] = *status; + } + return tile; }
M
src/gba/renderers/tile-cache.h
→
src/gba/renderers/tile-cache.h
@@ -13,13 +13,18 @@
DECL_BITFIELD(GBAVideoTileCacheConfiguration, uint32_t); DECL_BIT(GBAVideoTileCacheConfiguration, ShouldStore, 0); +struct GBAVideoTileCacheEntry { + uint32_t paletteVersion; + uint32_t vramVersion; + uint8_t vramClean; + uint8_t palette256; +}; + +typedef struct GBAVideoTileCacheEntry GBAVideoTileCacheStatus[1024 * 3][16]; + struct GBAVideoTileCache { uint16_t* cache; - struct GBAVideoTileCacheEntry { - uint32_t paletteVersion; - uint8_t vramClean; - uint8_t palette256; - } status[1024 * 3][16]; + GBAVideoTileCacheStatus status; uint32_t globalPaletteVersion[32]; uint32_t globalPalette256Version[2];@@ -37,8 +42,8 @@ void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo* video);
void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address); void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t address); const uint16_t* GBAVideoTileCacheGetTile16(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId); -const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId); +const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, GBAVideoTileCacheStatus handle, unsigned tileId, unsigned paletteId); const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId); -const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId); +const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, GBAVideoTileCacheStatus handle, unsigned tileId, unsigned paletteId); #endif
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -26,6 +26,7 @@ #include "gba/bios.h"
#include "gba/core.h" #include "gba/gba.h" #include "gba/extra/sharkport.h" +#include "gba/renderers/tile-cache.h" #endif #ifdef M_CORE_GB #include "gb/gb.h"@@ -585,6 +586,13 @@ if (!m_gameOpen || mCoreThreadIsActive(&m_threadContext)) {
return; } mCoreThreadJoin(&m_threadContext); + +#ifdef M_CORE_GBA + if (m_tileCache) { + GBAVideoTileCacheDeinit(m_tileCache.get()); + m_tileCache.reset(); + } +#endif delete[] m_drawContext; delete[] m_frontBuffer;@@ -1192,3 +1200,21 @@ keyReleased(k);
} } } + +#ifdef M_CORE_GBA +struct GBAVideoTileCache* GameController::tileCache() { + if (platform() != PLATFORM_GBA) { + return nullptr; + } + if (m_tileCache) { + return m_tileCache.get(); + } + threadInterrupt(); + GBA* gba = static_cast<GBA*>(m_threadContext.core->board); + m_tileCache = std::unique_ptr<GBAVideoTileCache>(new GBAVideoTileCache); + GBAVideoTileCacheInit(m_tileCache.get()); + GBAVideoTileCacheAssociate(m_tileCache.get(), &gba->video); + threadContinue(); + return m_tileCache.get(); +} +#endif
M
src/platform/qt/GameController.h
→
src/platform/qt/GameController.h
@@ -28,6 +28,7 @@ #endif
} struct GBAAudio; +struct GBAVideoTileCache; struct mCoreConfig; struct Configuration; struct mDebugger;@@ -83,6 +84,10 @@
#ifdef USE_GDB_STUB mDebugger* debugger(); void setDebugger(mDebugger*); +#endif + +#ifdef M_CORE_GBA + GBAVideoTileCache* tileCache(); #endif signals:@@ -209,6 +214,10 @@ bool m_turbo;
bool m_turboForced; float m_turboSpeed; bool m_wasPaused; + +#ifdef M_CORE_GBA + std::unique_ptr<GBAVideoTileCache> m_tileCache; +#endif bool m_audioChannels[6]; bool m_videoLayers[5];
M
src/platform/qt/TileView.cpp
→
src/platform/qt/TileView.cpp
@@ -19,10 +19,11 @@
TileView::TileView(GameController* controller, QWidget* parent) : QWidget(parent) , m_controller(controller) + , m_tileStatus{} + , m_tileCache(controller->tileCache()) , m_paletteId(0) { m_ui.setupUi(this); - GBAVideoTileCacheInit(&m_tileCache); m_ui.preview->setDimensions(QSize(8, 8)); m_updateTimer.setSingleShot(true);@@ -46,31 +47,22 @@ updateTiles(true);
}); } -TileView::~TileView() { - if (m_controller->isLoaded() && m_controller->thread() && m_controller->thread()->core) { - GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board); - gba->video.renderer->cache = nullptr; - } - - GBAVideoTileCacheDeinit(&m_tileCache); -} - void TileView::selectIndex(int index) { const uint16_t* data; m_ui.tileId->setText(QString::number(index)); if (m_ui.palette256->isChecked()) { m_ui.address->setText(tr("0x%0").arg(index * 64 | BASE_VRAM, 8, 16, QChar('0'))); if (index < 1024) { - data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 0); + data = GBAVideoTileCacheGetTile256(m_tileCache, index, 0); } else { - data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 1); + data = GBAVideoTileCacheGetTile256(m_tileCache, index, 1); } } else { m_ui.address->setText(tr("0x%0").arg(index * 32 | BASE_VRAM, 8, 16, QChar('0'))); if (index < 2048) { - data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId); + data = GBAVideoTileCacheGetTile16(m_tileCache, index, m_paletteId); } else { - data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId + 16); + data = GBAVideoTileCacheGetTile16(m_tileCache, index, m_paletteId + 16); } } for (int i = 0; i < 64; ++i) {@@ -84,43 +76,40 @@ if (!m_controller->thread() || !m_controller->thread()->core) {
return; } - GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board); - GBAVideoTileCacheAssociate(&m_tileCache, &gba->video); - if (m_ui.palette256->isChecked()) { m_ui.tiles->setTileCount(1536); for (int i = 0; i < 1024; ++i) { - const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 0); + const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(m_tileCache, m_tileStatus, i, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(&m_tileCache, i, 0)); + m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(m_tileCache, i, 0)); } } for (int i = 1024; i < 1536; ++i) { - const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 1); + const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(m_tileCache, m_tileStatus, i, 1); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(&m_tileCache, i, 1)); + m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile256(m_tileCache, i, 1)); } } } else { m_ui.tiles->setTileCount(3072); for (int i = 0; i < 2048; ++i) { - const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId); + const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(m_tileCache, m_tileStatus, i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(&m_tileCache, i, m_paletteId)); + m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(m_tileCache, i, m_paletteId)); } } for (int i = 2048; i < 3072; ++i) { - const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId + 16); + const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(m_tileCache, m_tileStatus, i, m_paletteId + 16); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(&m_tileCache, i, m_paletteId + 16)); + m_ui.tiles->setTile(i, GBAVideoTileCacheGetTile16(m_tileCache, i, m_paletteId + 16)); } } }
M
src/platform/qt/TileView.h
→
src/platform/qt/TileView.h
@@ -23,7 +23,6 @@ Q_OBJECT
public: TileView(GameController* controller, QWidget* parent = nullptr); - virtual ~TileView(); public slots: void updateTiles(bool force = false);@@ -40,7 +39,8 @@ private:
Ui::TileView m_ui; GameController* m_controller; - GBAVideoTileCache m_tileCache; + GBAVideoTileCache* m_tileCache; + GBAVideoTileCacheStatus m_tileStatus; int m_paletteId; QTimer m_updateTimer; };