GB Timer: Fix TAC write fix

This commit is contained in:
Vicki Pfau 2017-06-16 21:35:04 -07:00
parent c1a4f17ebd
commit 3c64a2e432
3 changed files with 12 additions and 15 deletions

View File

@ -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

View File

@ -91,3 +91,7 @@ int32_t mTimingNextEvent(struct mTiming* timing) {
}
return next->when - timing->masterCycles;
}
int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) {
return event->when - timing->masterCycles;
}

View File

@ -9,8 +9,6 @@
#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 @@ void _GBTimerIncrement(struct mTiming* timing, void* context, uint32_t cyclesLat
++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 @@ void _GBTimerUpdateDIV(struct GBTimer* timer, uint32_t cyclesLate) {
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 @@ uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) {
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;
}