mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Allow multiple handles into the same tile cache
This commit is contained in:
parent
250c19b91c
commit
9bef681c7d
1
CHANGES
1
CHANGES
|
@ -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:
|
||||
|
|
|
@ -46,6 +46,7 @@ void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo
|
|||
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,20 +137,23 @@ const uint16_t* GBAVideoTileCacheGetTile16(struct GBAVideoTileCache* cache, unsi
|
|||
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;
|
||||
}
|
||||
return NULL;
|
||||
if (memcmp(status, &handle[tileId][paletteId & 0xF], sizeof(*status))) {
|
||||
tile = _tileLookup(cache, tileId, paletteId);
|
||||
handle[tileId][paletteId & 0xF] = *status;
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
|
||||
const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
|
||||
struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId];
|
||||
uint16_t* tile = _tileLookup(cache, tileId, paletteId);
|
||||
|
@ -162,15 +166,19 @@ const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, uns
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -13,13 +13,18 @@ struct GBAVideo;
|
|||
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
|
|||
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
|
||||
|
|
|
@ -26,6 +26,7 @@ extern "C" {
|
|||
#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"
|
||||
|
@ -586,6 +587,13 @@ void GameController::cleanGame() {
|
|||
}
|
||||
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 @@ void GameController::updateAutofire() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
|
@ -28,6 +28,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
struct GBAAudio;
|
||||
struct GBAVideoTileCache;
|
||||
struct mCoreConfig;
|
||||
struct Configuration;
|
||||
struct mDebugger;
|
||||
|
@ -85,6 +86,10 @@ public:
|
|||
void setDebugger(mDebugger*);
|
||||
#endif
|
||||
|
||||
#ifdef M_CORE_GBA
|
||||
GBAVideoTileCache* tileCache();
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void frameAvailable(const uint32_t*);
|
||||
void gameStarted(mCoreThread*, const QString& fname);
|
||||
|
@ -210,6 +215,10 @@ private:
|
|||
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];
|
||||
|
||||
|
|
|
@ -19,10 +19,11 @@ using namespace QGBA;
|
|||
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 @@ TileView::TileView(GameController* controller, QWidget* parent)
|
|||
});
|
||||
}
|
||||
|
||||
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 @@ void TileView::updateTiles(bool force) {
|
|||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue