GB Timer: Fix TAC write fix
Vicki Pfau vi@endrift.com
Fri, 16 Jun 2017 21:35:04 -0700
3 files changed,
12 insertions(+),
15 deletions(-)
M
include/mgba/core/timing.h
→
include/mgba/core/timing.h
@@ -38,6 +38,7 @@ bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent*);
int32_t mTimingTick(struct mTiming* timing, int32_t cycles); int32_t mTimingCurrentTime(const struct mTiming* timing); int32_t mTimingNextEvent(struct mTiming* timing); +int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent*); CXX_GUARD_END
M
src/core/timing.c
→
src/core/timing.c
@@ -91,3 +91,7 @@ return INT_MAX;
} return next->when - timing->masterCycles; } + +int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) { + return event->when - timing->masterCycles; +}
M
src/gb/timer.c
→
src/gb/timer.c
@@ -9,8 +9,6 @@ #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);@@ -36,12 +34,8 @@ }
++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) + (timer->nextDiv / GB_DMG_DIV_PERIOD); + int divsToGo = 16 - (timer->internalDiv & 15); int timaToGo = INT_MAX; if (timer->timaPeriod) { timaToGo = timer->timaPeriod - (timer->internalDiv & (timer->timaPeriod - 1));@@ -49,12 +43,8 @@ }
if (timaToGo < divsToGo) { divsToGo = timaToGo; } - 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); + timer->nextDiv = GB_DMG_DIV_PERIOD * divsToGo; + mTimingSchedule(timing, &timer->event, timer->nextDiv - cyclesLate); } void GBTimerReset(struct GBTimer* timer) {@@ -96,11 +86,13 @@ case 3:
timer->timaPeriod = 256 >> 4; break; } + + timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); + mTimingDeschedule(&timer->p->timing, &timer->event); + mTimingSchedule(&timer->p->timing, &timer->event, 0); } else { timer->timaPeriod = 0; } - mTimingDeschedule(&timer->p->timing, &timer->event); - _GBTimerUpdateDIV(timer, 0); return tac; }