diff --git a/CHANGES b/CHANGES index ed885288f..24ce59c25 100644 --- a/CHANGES +++ b/CHANGES @@ -48,6 +48,7 @@ Bugfixes: - Wii: Fix screen tear when unpausing - GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978) - GBA Hardware: RTC accuracy improvements + - GB Timer: Minor accuracy improvements Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml b/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml deleted file mode 100644 index a697ada66..000000000 --- a/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml +++ /dev/null @@ -1 +0,0 @@ -fail: true diff --git a/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml b/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml deleted file mode 100644 index a697ada66..000000000 --- a/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml +++ /dev/null @@ -1 +0,0 @@ -fail: true diff --git a/src/gb/io.c b/src/gb/io.c index c6e065b95..21a7f696e 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -380,8 +380,17 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { } break; 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: - // Handled transparently by the registers + if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) { + gb->memory.io[REG_TIMA] = value; + } break; case REG_TAC: value = GBTimerUpdateTAC(&gb->timer, value); diff --git a/src/gb/timer.c b/src/gb/timer.c index d5fe20089..736ca3cfb 100644 --- a/src/gb/timer.c +++ b/src/gb/timer.c @@ -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) { ++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; @@ -69,11 +69,11 @@ void GBTimerReset(struct GBTimer* timer) { void GBTimerDivReset(struct GBTimer* timer) { timer->nextDiv -= mTimingUntil(&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) { ++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; @@ -101,7 +101,7 @@ uint8_t GBTimerUpdateTAC(struct GBTimer* timer, GBRegisterTAC tac) { timer->nextDiv -= mTimingUntil(&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; mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv); } else {