all repos — mgba @ 0786d7fe3b6c78f46236cbb8fe2b91793d5304be

mGBA Game Boy Advance Emulator

GBA Timer: Fix reload timing regression
Vicki Pfau vi@endrift.com
Tue, 04 Jul 2017 09:59:26 -0700
commit

0786d7fe3b6c78f46236cbb8fe2b91793d5304be

parent

7a5190e95e517f8b1030340e72ae0288bb601f29

3 files changed, 5 insertions(+), 4 deletions(-)

jump to
M include/mgba/internal/gba/timer.hinclude/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.csrc/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.csrc/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);