mirror of https://github.com/mgba-emu/mgba.git
GBA Timers: Improve timer startup emulation
This commit is contained in:
parent
ab1d825e30
commit
0e49b2d391
1
CHANGES
1
CHANGES
|
@ -92,6 +92,7 @@ Emulation fixes:
|
||||||
- ARM: Fix stepping when events are pending
|
- ARM: Fix stepping when events are pending
|
||||||
- GBA DMA: Fix case where DMAs could get misaligned (fixes mgba.io/i/1092)
|
- 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 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 OpenGL renderer 512x512 backgrounds (fixes mgba.io/i/1572)
|
||||||
- GBA Video: Fix BLDY for semitransparent sprite on non-target-2 backgrounds
|
- GBA Video: Fix BLDY for semitransparent sprite on non-target-2 backgrounds
|
||||||
- GBA Video: Fix effects blending improperly in some non-last windows
|
- GBA Video: Fix effects blending improperly in some non-last windows
|
||||||
|
|
|
@ -712,16 +712,16 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
// Reading this takes two cycles (1N+1I), so let's remove them preemptively
|
// Reading this takes two cycles (1N+1I), so let's remove them preemptively
|
||||||
case REG_TM0CNT_LO:
|
case REG_TM0CNT_LO:
|
||||||
GBATimerUpdateRegister(gba, 0, 4);
|
GBATimerUpdateRegister(gba, 0, 2);
|
||||||
break;
|
break;
|
||||||
case REG_TM1CNT_LO:
|
case REG_TM1CNT_LO:
|
||||||
GBATimerUpdateRegister(gba, 1, 4);
|
GBATimerUpdateRegister(gba, 1, 2);
|
||||||
break;
|
break;
|
||||||
case REG_TM2CNT_LO:
|
case REG_TM2CNT_LO:
|
||||||
GBATimerUpdateRegister(gba, 2, 4);
|
GBATimerUpdateRegister(gba, 2, 2);
|
||||||
break;
|
break;
|
||||||
case REG_TM3CNT_LO:
|
case REG_TM3CNT_LO:
|
||||||
GBATimerUpdateRegister(gba, 3, 4);
|
GBATimerUpdateRegister(gba, 3, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_KEYINPUT:
|
case REG_KEYINPUT:
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
#include <mgba/internal/gba/gba.h>
|
#include <mgba/internal/gba/gba.h>
|
||||||
#include <mgba/internal/gba/io.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))
|
#define REG_TMCNT_LO(X) (REG_TM0CNT_LO + ((X) << 2))
|
||||||
|
|
||||||
static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) {
|
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)) {
|
if (GBATimerFlagsIsCountUp(timer->flags)) {
|
||||||
gba->memory.io[REG_TMCNT_LO(timerId) >> 1] = timer->reload;
|
gba->memory.io[REG_TMCNT_LO(timerId) >> 1] = timer->reload;
|
||||||
} else {
|
} else {
|
||||||
GBATimerUpdateRegister(gba, timerId, TIMER_RELOAD_DELAY + cyclesLate);
|
GBATimerUpdateRegister(gba, timerId, cyclesLate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GBATimerFlagsIsDoIrq(timer->flags)) {
|
if (GBATimerFlagsIsDoIrq(timer->flags)) {
|
||||||
|
@ -150,14 +147,14 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
|
||||||
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
||||||
gba->memory.io[REG_TMCNT_LO(timer) >> 1] = currentTimer->reload;
|
gba->memory.io[REG_TMCNT_LO(timer) >> 1] = currentTimer->reload;
|
||||||
int32_t tickMask = (1 << prescaleBits) - 1;
|
int32_t tickMask = (1 << prescaleBits) - 1;
|
||||||
currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask;
|
currentTimer->lastEvent = mTimingCurrentTime(&gba->timing) & ~tickMask;
|
||||||
GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY);
|
GBATimerUpdateRegister(gba, timer, 0);
|
||||||
} else if (wasEnabled && !GBATimerFlagsIsEnable(currentTimer->flags)) {
|
} else if (wasEnabled && !GBATimerFlagsIsEnable(currentTimer->flags)) {
|
||||||
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
||||||
} else if (GBATimerFlagsIsEnable(currentTimer->flags) && GBATimerFlagsGetPrescaleBits(currentTimer->flags) != oldPrescale && !GBATimerFlagsIsCountUp(currentTimer->flags)) {
|
} else if (GBATimerFlagsIsEnable(currentTimer->flags) && GBATimerFlagsGetPrescaleBits(currentTimer->flags) != oldPrescale && !GBATimerFlagsIsCountUp(currentTimer->flags)) {
|
||||||
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
||||||
int32_t tickMask = (1 << prescaleBits) - 1;
|
int32_t tickMask = (1 << prescaleBits) - 1;
|
||||||
currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask;
|
currentTimer->lastEvent = mTimingCurrentTime(&gba->timing) & ~tickMask;
|
||||||
GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY);
|
GBATimerUpdateRegister(gba, timer, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue