mirror of https://github.com/mgba-emu/mgba.git
This commit is contained in:
parent
c353e1254a
commit
e2a5efeaf7
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
/* Copyright (c) 2013-2018 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
|
@ -12,6 +12,8 @@
|
|||
#define TIMER_RELOAD_DELAY 0
|
||||
#define TIMER_STARTUP_DELAY 2
|
||||
|
||||
#define REG_TMCNT_LO(X) (REG_TM0CNT_LO + (X << 2))
|
||||
|
||||
static void GBATimerIrq(struct GBA* gba, int timerId) {
|
||||
struct GBATimer* timer = &gba->timers[timerId];
|
||||
if (GBATimerFlagsIsIrqPending(timer->flags)) {
|
||||
|
@ -46,11 +48,6 @@ static void GBATimerIrq3(struct mTiming* timing, void* context, uint32_t cyclesL
|
|||
|
||||
static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) {
|
||||
struct GBATimer* timer = &gba->timers[timerId];
|
||||
gba->memory.io[(REG_TM0CNT_LO >> 1) + (timerId << 1)] = timer->reload;
|
||||
int32_t currentTime = mTimingCurrentTime(&gba->timing) - cyclesLate;
|
||||
int32_t tickMask = (1 << GBATimerFlagsGetPrescaleBits(timer->flags)) - 1;
|
||||
currentTime &= ~tickMask;
|
||||
timer->lastEvent = currentTime;
|
||||
GBATimerUpdateRegister(gba, timerId, TIMER_RELOAD_DELAY + cyclesLate);
|
||||
|
||||
if (GBATimerFlagsIsDoIrq(timer->flags)) {
|
||||
|
@ -143,20 +140,29 @@ void GBATimerUpdateRegister(struct GBA* gba, int timer, int32_t cyclesLate) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Align timer
|
||||
int prescaleBits = GBATimerFlagsGetPrescaleBits(currentTimer->flags);
|
||||
int32_t currentTime = mTimingCurrentTime(&gba->timing) - cyclesLate;
|
||||
int32_t tickMask = (1 << prescaleBits) - 1;
|
||||
currentTime &= ~tickMask;
|
||||
|
||||
// Update register
|
||||
int32_t tickIncrement = currentTime - currentTimer->lastEvent;
|
||||
currentTimer->lastEvent = currentTime;
|
||||
tickIncrement >>= prescaleBits;
|
||||
tickIncrement += gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1];
|
||||
gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = tickIncrement;
|
||||
if (!mTimingIsScheduled(&gba->timing, ¤tTimer->event)) {
|
||||
tickIncrement = (0x10000 - tickIncrement) << prescaleBits;
|
||||
currentTime -= mTimingCurrentTime(&gba->timing) - cyclesLate;
|
||||
mTimingSchedule(&gba->timing, ¤tTimer->event, tickIncrement + currentTime);
|
||||
tickIncrement += gba->memory.io[REG_TMCNT_LO(timer) >> 1];
|
||||
while (tickIncrement >= 0x10000) {
|
||||
tickIncrement -= 0x10000 - currentTimer->reload;
|
||||
}
|
||||
gba->memory.io[REG_TMCNT_LO(timer) >> 1] = tickIncrement;
|
||||
|
||||
// Schedule next update
|
||||
tickIncrement = (0x10000 - tickIncrement) << prescaleBits;
|
||||
currentTime += tickIncrement;
|
||||
currentTime &= ~tickMask;
|
||||
currentTime -= mTimingCurrentTime(&gba->timing);
|
||||
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
||||
mTimingSchedule(&gba->timing, ¤tTimer->event, currentTime);
|
||||
}
|
||||
|
||||
void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t reload) {
|
||||
|
@ -190,7 +196,7 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
|
|||
currentTimer->flags = GBATimerFlagsTestFillEnable(currentTimer->flags, control & 0x0080);
|
||||
if (!wasEnabled && GBATimerFlagsIsEnable(currentTimer->flags)) {
|
||||
mTimingDeschedule(&gba->timing, ¤tTimer->event);
|
||||
gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload;
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue