GBA Timer: Improve accuracy of timers
Vicki Pfau vi@endrift.com
Sun, 02 Jul 2017 10:06:05 -0700
2 files changed,
11 insertions(+),
5 deletions(-)
M
CHANGES
→
CHANGES
@@ -75,6 +75,8 @@ - Qt: Fix game unpausing after frame advancing and refocusing
- GB Timer: Fix sub-M-cycle DIV reset timing and edge triggering - Core: Fix interrupting a thread while on the thread (fixes mgba.io/i/692) - Core: Fix directory sets crashing on close if base isn't properly detached + - Qt: Fix window icon being stretched + - Qt: Fix data directory path Misc: - SDL: Remove scancode key input - GBA Video: Clean up unused timers@@ -145,6 +147,7 @@ - GB: Reset with initial state of DIV register
- GB MBC: New MBC7 implementation - Qt: Better highlight active key in control binding - Core: Improved threading interrupted detection + - GBA Timer: Improve accuracy of timers 0.6 beta 2: (Future) Bugfixes:@@ -154,6 +157,7 @@ - Qt: Fix initial window size (fixes mgba.io/i/766)
- Qt: Fix data directory path Misc: - Qt: Add language selector + - GBA Timer: Improve accuracy of timers 0.6 beta 1: (2017-06-29) - Initial beta for 0.6
M
src/gba/timer.c
→
src/gba/timer.c
@@ -103,20 +103,22 @@ struct GBATimer* currentTimer = &gba->timers[timer];
GBATimerUpdateRegister(gba, timer); unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(currentTimer->flags); + unsigned prescaleBits; switch (control & 0x0003) { case 0x0000: - currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 0); + prescaleBits = 0; break; case 0x0001: - currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 6); + prescaleBits = 6; break; case 0x0002: - currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 8); + prescaleBits = 8; break; case 0x0003: - currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 10); + prescaleBits = 10; break; } + currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, prescaleBits); currentTimer->flags = GBATimerFlagsTestFillCountUp(currentTimer->flags, timer > 0 && (control & 0x0004)); currentTimer->flags = GBATimerFlagsTestFillDoIrq(currentTimer->flags, control & 0x0040); currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << GBATimerFlagsGetPrescaleBits(currentTimer->flags);@@ -125,7 +127,7 @@ currentTimer->flags = GBATimerFlagsTestFillEnable(currentTimer->flags, control & 0x0080);
if (!wasEnabled && GBATimerFlagsIsEnable(currentTimer->flags)) { mTimingDeschedule(&gba->timing, ¤tTimer->event); if (!GBATimerFlagsIsCountUp(currentTimer->flags)) { - mTimingSchedule(&gba->timing, ¤tTimer->event, currentTimer->overflowInterval); + mTimingSchedule(&gba->timing, ¤tTimer->event, currentTimer->overflowInterval + 7 - 6 * prescaleBits); } gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload; currentTimer->oldReload = currentTimer->reload;