GB Timer: Fix TIMA/TMA timing

This commit is contained in:
Vicki Pfau 2018-02-03 23:12:57 -08:00
parent a382c1ee9b
commit 7ea686a7d9
5 changed files with 15 additions and 7 deletions

View File

@ -48,6 +48,7 @@ Bugfixes:
- Wii: Fix screen tear when unpausing - Wii: Fix screen tear when unpausing
- GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978) - GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
- GBA Hardware: RTC accuracy improvements - GBA Hardware: RTC accuracy improvements
- GB Timer: Minor accuracy improvements
Misc: Misc:
- GBA Timer: Use global cycles for timers - GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)

View File

@ -380,8 +380,17 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
} }
break; break;
case REG_TIMA: case REG_TIMA:
if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) {
mTimingDeschedule(&gb->timing, &gb->timer.irq);
}
if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
return;
}
break;
case REG_TMA: case REG_TMA:
// Handled transparently by the registers if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
gb->memory.io[REG_TIMA] = value;
}
break; break;
case REG_TAC: case REG_TAC:
value = GBTimerUpdateTAC(&gb->timer, value); value = GBTimerUpdateTAC(&gb->timer, value);

View File

@ -27,7 +27,7 @@ static void _GBTimerDivIncrement(struct GBTimer* timer, uint32_t cyclesLate) {
if (timer->timaPeriod > 0 && (timer->internalDiv & (timer->timaPeriod - 1)) == timer->timaPeriod - 1) { if (timer->timaPeriod > 0 && (timer->internalDiv & (timer->timaPeriod - 1)) == timer->timaPeriod - 1) {
++timer->p->memory.io[REG_TIMA]; ++timer->p->memory.io[REG_TIMA];
if (!timer->p->memory.io[REG_TIMA]) { if (!timer->p->memory.io[REG_TIMA]) {
mTimingSchedule(&timer->p->timing, &timer->irq, 4 - cyclesLate); mTimingSchedule(&timer->p->timing, &timer->irq, 7 - ((timer->p->cpu->executionState - cyclesLate) & 3));
} }
} }
++timer->internalDiv; ++timer->internalDiv;
@ -69,11 +69,11 @@ void GBTimerReset(struct GBTimer* timer) {
void GBTimerDivReset(struct GBTimer* timer) { void GBTimerDivReset(struct GBTimer* timer) {
timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event);
mTimingDeschedule(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event);
_GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3); _GBTimerDivIncrement(timer, 0);
if (((timer->internalDiv << 1) | ((timer->nextDiv >> 3) & 1)) & timer->timaPeriod) { if (((timer->internalDiv << 1) | ((timer->nextDiv >> 3) & 1)) & timer->timaPeriod) {
++timer->p->memory.io[REG_TIMA]; ++timer->p->memory.io[REG_TIMA];
if (!timer->p->memory.io[REG_TIMA]) { if (!timer->p->memory.io[REG_TIMA]) {
mTimingSchedule(&timer->p->timing, &timer->irq, 4 - ((timer->p->cpu->executionState + 1) & 3)); mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3));
} }
} }
timer->p->memory.io[REG_DIV] = 0; timer->p->memory.io[REG_DIV] = 0;
@ -101,7 +101,7 @@ uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) {
timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event);
mTimingDeschedule(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event);
_GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3); _GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 2) & 3);
timer->nextDiv += GB_DMG_DIV_PERIOD; timer->nextDiv += GB_DMG_DIV_PERIOD;
mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv); mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv);
} else { } else {