all repos — mgba @ 59922fe2e931ef876f10e4e4cbad92b5d76255fb

mGBA Game Boy Advance Emulator

GB Timer: Fix DIV batching if TAC changes
Vicki Pfau vi@endrift.com
Mon, 12 Jun 2017 07:14:19 -0700
commit

59922fe2e931ef876f10e4e4cbad92b5d76255fb

parent

126afa12d9ac4bbbc1d2db423aafb6ccf6dcf5a1

2 files changed, 16 insertions(+), 3 deletions(-)

jump to
M CHANGESCHANGES

@@ -66,6 +66,7 @@ - Qt: Disable "New multiplayer window" when MAX_GBAS is reached (fixes mgba.io/i/107)

- LR35902: Fix decoding LD r, $imm and 0-valued immediates (fixes mgba.io/i/735) - GB: Fix STAT blocking - GB MBC: Fix swapping carts not detect new MBC + - GB Timer: Fix DIV batching if TAC changes Misc: - SDL: Remove scancode key input - GBA Video: Clean up unused timers
M src/gb/timer.csrc/gb/timer.c

@@ -9,6 +9,8 @@ #include <mgba/internal/gb/gb.h>

#include <mgba/internal/gb/io.h> #include <mgba/internal/gb/serialize.h> +static void _GBTimerUpdateDIV(struct GBTimer* timer, uint32_t cyclesLate); + void _GBTimerIRQ(struct mTiming* timing, void* context, uint32_t cyclesLate) { UNUSED(timing); UNUSED(cyclesLate);

@@ -34,8 +36,12 @@ }

++timer->internalDiv; timer->p->memory.io[REG_DIV] = timer->internalDiv >> 4; } + _GBTimerUpdateDIV(timer, cyclesLate); +} + +void _GBTimerUpdateDIV(struct GBTimer* timer, uint32_t cyclesLate) { // Batch div increments - int divsToGo = 16 - (timer->internalDiv & 15); + int divsToGo = 16 - (timer->internalDiv & 15) + (timer->nextDiv / GB_DMG_DIV_PERIOD); int timaToGo = INT_MAX; if (timer->timaPeriod) { timaToGo = timer->timaPeriod - (timer->internalDiv & (timer->timaPeriod - 1));

@@ -43,8 +49,12 @@ }

if (timaToGo < divsToGo) { divsToGo = timaToGo; } - timer->nextDiv = GB_DMG_DIV_PERIOD * divsToGo; - mTimingSchedule(timing, &timer->event, timer->nextDiv - cyclesLate); + if (divsToGo > 16) { + divsToGo = 16; + } + timer->nextDiv &= GB_DMG_DIV_PERIOD - 1; + timer->nextDiv += GB_DMG_DIV_PERIOD * divsToGo; + mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv - cyclesLate); } void GBTimerReset(struct GBTimer* timer) {

@@ -89,6 +99,8 @@ }

} else { timer->timaPeriod = 0; } + mTimingDeschedule(&timer->p->timing, &timer->event); + _GBTimerUpdateDIV(timer, 0); return tac; }