all repos — mgba @ 9bef681c7d15ab97afdc306709ea2160ab649d82

mGBA Game Boy Advance Emulator

GBA Video: Allow multiple handles into the same tile cache
Jeffrey Pfau jeffrey@endrift.com
Sun, 16 Oct 2016 18:23:28 -0700
commit

9bef681c7d15ab97afdc306709ea2160ab649d82

parent

250c19b91c738716e981d52f4fb1edd8b6c16a51

M CHANGESCHANGES

@@ -16,6 +16,7 @@ Misc:

- SDL: Remove scancode key input - GBA Video: Clean up unused timers - Test: Add a basic test suite + - GBA Video: Allow multiple handles into the same tile cache 0.5.1: (2016-10-05) Bugfixes:
M src/gba/renderers/tile-cache.csrc/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.hsrc/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.cppsrc/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.hsrc/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.cppsrc/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.hsrc/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; };