all repos — mgba @ 3c64a2e432fa6a230ef2055f461e09d8357fea36

mGBA Game Boy Advance Emulator

GB Timer: Fix TAC write fix
Vicki Pfau vi@endrift.com
Fri, 16 Jun 2017 21:35:04 -0700
commit

3c64a2e432fa6a230ef2055f461e09d8357fea36

parent

c1a4f17ebd812c37a2b732391e95c504d7456e1f

3 files changed, 12 insertions(+), 15 deletions(-)

jump to
M include/mgba/core/timing.hinclude/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.csrc/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.csrc/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; }