GBA Timer: Fix reload timing regression
Vicki Pfau vi@endrift.com
Tue, 04 Jul 2017 09:59:26 -0700
3 files changed,
5 insertions(+),
4 deletions(-)
M
include/mgba/internal/gba/timer.h
→
include/mgba/internal/gba/timer.h
@@ -23,7 +23,6 @@ struct GBATimer {
uint16_t reload; int32_t lastEvent; struct mTimingEvent event; - int32_t overflowInterval; GBATimerFlags flags; };
M
src/gba/io.c
→
src/gba/io.c
@@ -928,7 +928,6 @@ STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload); STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent); STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent); - STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval); STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags); STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);@@ -958,7 +957,6 @@ when = 0x400 - (when & 0x3FF);
mTimingSchedule(&gba->timing, &gba->timerMaster, when); for (i = 0; i < 4; ++i) { LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload); - LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval); LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags); if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) { // Overwrite invalid values in savestate
M
src/gba/timer.c
→
src/gba/timer.c
@@ -13,7 +13,11 @@
static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) { struct GBATimer* timer = &gba->timers[timerId]; gba->memory.io[(REG_TM0CNT_LO >> 1) + (timerId << 1)] = timer->reload; - GBATimerUpdateRegister(gba, timerId, cyclesLate); + int32_t currentTime = mTimingCurrentTime(&gba->timing) - cyclesLate; + int32_t tickMask = (1 << GBATimerFlagsGetPrescaleBits(timer->flags)) - 1; + currentTime &= ~tickMask; + timer->lastEvent = currentTime; + GBATimerUpdateRegister(gba, timerId, 0); if (GBATimerFlagsIsDoIrq(timer->flags)) { GBARaiseIRQ(gba, IRQ_TIMER0 + timerId);