[teagba] Change sprite buffer to fully update on every VSync

This commit is contained in:
Gary Talent 2023-12-22 01:02:24 -06:00
parent d29118d783
commit 6de0e882e9
2 changed files with 12 additions and 20 deletions

View File

@ -33,9 +33,10 @@ struct OX_ALIGN8 GbaSpriteAttrUpdate {
uint16_t attr1 = 0; uint16_t attr1 = 0;
uint16_t attr2 = 0; uint16_t attr2 = 0;
uint16_t idx = 0; uint16_t idx = 0;
}; };
GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept;
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept; void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;
void applySpriteUpdates() noexcept; void applySpriteUpdates() noexcept;

View File

@ -10,32 +10,23 @@
namespace teagba { namespace teagba {
static volatile uint16_t g_spriteUpdates = 0;
static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer; static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept { GbaSpriteAttrUpdate &spriteAttr(size_t i) noexcept {
// block until g_spriteUpdates is less than buffer len return g_spriteBuffer[i];
if (g_spriteUpdates >= g_spriteBuffer.size()) [[unlikely]] {
teagba_vblankintrwait();
} }
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
const auto ie = REG_IE; // disable vblank interrupt handler const auto ie = REG_IE; // disable vblank interrupt handler
REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler REG_IE = REG_IE & static_cast<uint16_t>(~teagba::Int_vblank); // disable vblank interrupt handler
const auto updateCnt = g_spriteUpdates; g_spriteBuffer[upd.idx] = upd;
g_spriteBuffer[updateCnt] = upd;
g_spriteUpdates = updateCnt + 1;
REG_IE = ie; // enable vblank interrupt handler REG_IE = ie; // enable vblank interrupt handler
} }
void applySpriteUpdates() noexcept { void applySpriteUpdates() noexcept {
// copy g_spriteUpdates to allow it to use a register instead of reading for (auto const&oa : g_spriteBuffer) {
// from memory every iteration of the loop, needed because g_spriteUpdates
// is volatile
const unsigned updates = g_spriteUpdates;
for (unsigned i = 0; i < updates; ++i) {
const auto &oa = g_spriteBuffer[i];
MEM_OAM[oa.idx] = std::bit_cast<uint64_t>(oa); MEM_OAM[oa.idx] = std::bit_cast<uint64_t>(oa);
} }
g_spriteUpdates = 0;
} }
} }