GBA Timer: Improve accuracy of timers

This commit is contained in:
Vicki Pfau 2017-07-02 10:06:05 -07:00
parent 11354ac23e
commit da50382cd4
2 changed files with 11 additions and 5 deletions

View File

@ -75,6 +75,8 @@ Bugfixes:
- GB Timer: Fix sub-M-cycle DIV reset timing and edge triggering - 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 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 - 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: Misc:
- SDL: Remove scancode key input - SDL: Remove scancode key input
- GBA Video: Clean up unused timers - GBA Video: Clean up unused timers
@ -145,6 +147,7 @@ Misc:
- GB MBC: New MBC7 implementation - GB MBC: New MBC7 implementation
- Qt: Better highlight active key in control binding - Qt: Better highlight active key in control binding
- Core: Improved threading interrupted detection - Core: Improved threading interrupted detection
- GBA Timer: Improve accuracy of timers
0.6 beta 2: (Future) 0.6 beta 2: (Future)
Bugfixes: Bugfixes:
@ -154,6 +157,7 @@ Bugfixes:
- Qt: Fix data directory path - Qt: Fix data directory path
Misc: Misc:
- Qt: Add language selector - Qt: Add language selector
- GBA Timer: Improve accuracy of timers
0.6 beta 1: (2017-06-29) 0.6 beta 1: (2017-06-29)
- Initial beta for 0.6 - Initial beta for 0.6

View File

@ -103,20 +103,22 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
GBATimerUpdateRegister(gba, timer); GBATimerUpdateRegister(gba, timer);
unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(currentTimer->flags); unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(currentTimer->flags);
unsigned prescaleBits;
switch (control & 0x0003) { switch (control & 0x0003) {
case 0x0000: case 0x0000:
currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 0); prescaleBits = 0;
break; break;
case 0x0001: case 0x0001:
currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 6); prescaleBits = 6;
break; break;
case 0x0002: case 0x0002:
currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 8); prescaleBits = 8;
break; break;
case 0x0003: case 0x0003:
currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, 10); prescaleBits = 10;
break; break;
} }
currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, prescaleBits);
currentTimer->flags = GBATimerFlagsTestFillCountUp(currentTimer->flags, timer > 0 && (control & 0x0004)); currentTimer->flags = GBATimerFlagsTestFillCountUp(currentTimer->flags, timer > 0 && (control & 0x0004));
currentTimer->flags = GBATimerFlagsTestFillDoIrq(currentTimer->flags, control & 0x0040); currentTimer->flags = GBATimerFlagsTestFillDoIrq(currentTimer->flags, control & 0x0040);
currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << GBATimerFlagsGetPrescaleBits(currentTimer->flags); currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << GBATimerFlagsGetPrescaleBits(currentTimer->flags);
@ -125,7 +127,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
if (!wasEnabled && GBATimerFlagsIsEnable(currentTimer->flags)) { if (!wasEnabled && GBATimerFlagsIsEnable(currentTimer->flags)) {
mTimingDeschedule(&gba->timing, &currentTimer->event); mTimingDeschedule(&gba->timing, &currentTimer->event);
if (!GBATimerFlagsIsCountUp(currentTimer->flags)) { if (!GBATimerFlagsIsCountUp(currentTimer->flags)) {
mTimingSchedule(&gba->timing, &currentTimer->event, currentTimer->overflowInterval); mTimingSchedule(&gba->timing, &currentTimer->event, currentTimer->overflowInterval + 7 - 6 * prescaleBits);
} }
gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload; gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload;
currentTimer->oldReload = currentTimer->reload; currentTimer->oldReload = currentTimer->reload;