GBA Timers: Improve timer startup emulation

This commit is contained in:
Vicki Pfau 2020-01-15 18:52:35 -08:00
parent ab1d825e30
commit 0e49b2d391
3 changed files with 10 additions and 12 deletions

View File

@ -92,6 +92,7 @@ Emulation fixes:
- ARM: Fix stepping when events are pending
- GBA DMA: Fix case where DMAs could get misaligned (fixes mgba.io/i/1092)
- GBA Memory: Fix open bus from IWRAM (fixes mgba.io/i/1575)
- GBA Timers: Improve timer startup emulation
- GBA Video: Fix OpenGL renderer 512x512 backgrounds (fixes mgba.io/i/1572)
- GBA Video: Fix BLDY for semitransparent sprite on non-target-2 backgrounds
- GBA Video: Fix effects blending improperly in some non-last windows

View File

@ -712,16 +712,16 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
switch (address) {
// Reading this takes two cycles (1N+1I), so let's remove them preemptively
case REG_TM0CNT_LO:
GBATimerUpdateRegister(gba, 0, 4);
GBATimerUpdateRegister(gba, 0, 2);
break;
case REG_TM1CNT_LO:
GBATimerUpdateRegister(gba, 1, 4);
GBATimerUpdateRegister(gba, 1, 2);
break;
case REG_TM2CNT_LO:
GBATimerUpdateRegister(gba, 2, 4);
GBATimerUpdateRegister(gba, 2, 2);
break;
case REG_TM3CNT_LO:
GBATimerUpdateRegister(gba, 3, 4);
GBATimerUpdateRegister(gba, 3, 2);
break;
case REG_KEYINPUT:

View File

@ -8,9 +8,6 @@
#include <mgba/internal/gba/gba.h>
#include <mgba/internal/gba/io.h>
#define TIMER_RELOAD_DELAY 0
#define TIMER_STARTUP_DELAY 2
#define REG_TMCNT_LO(X) (REG_TM0CNT_LO + ((X) << 2))
static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) {
@ -18,7 +15,7 @@ static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) {
if (GBATimerFlagsIsCountUp(timer->flags)) {
gba->memory.io[REG_TMCNT_LO(timerId) >> 1] = timer->reload;
} else {
GBATimerUpdateRegister(gba, timerId, TIMER_RELOAD_DELAY + cyclesLate);
GBATimerUpdateRegister(gba, timerId, cyclesLate);
}
if (GBATimerFlagsIsDoIrq(timer->flags)) {
@ -150,14 +147,14 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
mTimingDeschedule(&gba->timing, &currentTimer->event);
gba->memory.io[REG_TMCNT_LO(timer) >> 1] = currentTimer->reload;
int32_t tickMask = (1 << prescaleBits) - 1;
currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask;
GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY);
currentTimer->lastEvent = mTimingCurrentTime(&gba->timing) & ~tickMask;
GBATimerUpdateRegister(gba, timer, 0);
} else if (wasEnabled && !GBATimerFlagsIsEnable(currentTimer->flags)) {
mTimingDeschedule(&gba->timing, &currentTimer->event);
} else if (GBATimerFlagsIsEnable(currentTimer->flags) && GBATimerFlagsGetPrescaleBits(currentTimer->flags) != oldPrescale && !GBATimerFlagsIsCountUp(currentTimer->flags)) {
mTimingDeschedule(&gba->timing, &currentTimer->event);
int32_t tickMask = (1 << prescaleBits) - 1;
currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask;
GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY);
currentTimer->lastEvent = mTimingCurrentTime(&gba->timing) & ~tickMask;
GBATimerUpdateRegister(gba, timer, 0);
}
}