all repos — mgba @ fa92b4cd0e461ede2a70077c8acf87078a931d05

mGBA Game Boy Advance Emulator

GBA: Count up timers should not count themselves
Jeffrey Pfau jeffrey@endrift.com
Wed, 14 Sep 2016 01:34:53 -0700
commit

fa92b4cd0e461ede2a70077c8acf87078a931d05

parent

dd76386f4cee134237f6a86c37f178eeca8bd44b

3 files changed, 16 insertions(+), 9 deletions(-)

jump to
M CHANGESCHANGES

@@ -40,6 +40,7 @@ - GBA: Timer 0 cannot be count up

- Qt: Fix being unable to pause manually when using auto-pausing - GBA Memory: Fix ldm {pc} - GBA Video: Fix out-of-order OBJWIN + - GBA: Count up timers should not count themselves Misc: - 3DS: Use blip_add_delta_fast for a small speed improvement - OpenGL: Log shader compilation failure
M src/gba/gba.csrc/gba/gba.c

@@ -306,7 +306,7 @@ struct GBATimer* timer;

struct GBATimer* nextTimer; timer = &gba->timers[0]; - if (GBATimerFlagsIsEnable(timer->flags)) { + if (GBATimerFlagsIsEnable(timer->flags) && timer->nextEvent != INT_MAX) { timer->nextEvent -= cycles; timer->lastEvent -= cycles; while (timer->nextEvent <= 0) {

@@ -333,7 +333,7 @@ nextTimer = &gba->timers[1];

if (GBATimerFlagsIsCountUp(nextTimer->flags)) { ++gba->memory.io[REG_TM1CNT_LO >> 1]; if (!gba->memory.io[REG_TM1CNT_LO >> 1]) { - nextTimer->nextEvent = 0; + nextTimer->nextEvent = cycles; } } }

@@ -341,7 +341,7 @@ nextEvent = timer->nextEvent;

} timer = &gba->timers[1]; - if (GBATimerFlagsIsEnable(timer->flags)) { + if (GBATimerFlagsIsEnable(timer->flags) && timer->nextEvent != INT_MAX) { timer->nextEvent -= cycles; timer->lastEvent -= cycles; if (timer->nextEvent <= 0) {

@@ -372,7 +372,7 @@ nextTimer = &gba->timers[2];

if (GBATimerFlagsIsCountUp(nextTimer->flags)) { ++gba->memory.io[REG_TM2CNT_LO >> 1]; if (!gba->memory.io[REG_TM2CNT_LO >> 1]) { - nextTimer->nextEvent = 0; + nextTimer->nextEvent = cycles; } } }

@@ -382,7 +382,7 @@ }

} timer = &gba->timers[2]; - if (GBATimerFlagsIsEnable(timer->flags)) { + if (GBATimerFlagsIsEnable(timer->flags) && timer->nextEvent != INT_MAX) { timer->nextEvent -= cycles; timer->lastEvent -= cycles; if (timer->nextEvent <= 0) {

@@ -403,7 +403,7 @@ nextTimer = &gba->timers[3];

if (GBATimerFlagsIsCountUp(nextTimer->flags)) { ++gba->memory.io[REG_TM3CNT_LO >> 1]; if (!gba->memory.io[REG_TM3CNT_LO >> 1]) { - nextTimer->nextEvent = 0; + nextTimer->nextEvent = cycles; } } }

@@ -413,7 +413,7 @@ }

} timer = &gba->timers[3]; - if (GBATimerFlagsIsEnable(timer->flags)) { + if (GBATimerFlagsIsEnable(timer->flags) && timer->nextEvent != INT_MAX) { timer->nextEvent -= cycles; timer->lastEvent -= cycles; if (timer->nextEvent <= 0) {
M src/gba/io.csrc/gba/io.c

@@ -883,10 +883,16 @@ gba->timersEnabled = 0;

for (i = 0; i < 4; ++i) { LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload); LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload); - LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent); - LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent); LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval); LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags); + if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) { + // Overwrite invalid values in savestate + gba->timers[i].lastEvent = 0; + gba->timers[i].nextEvent = INT_MAX; + } else { + LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent); + LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent); + } LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io); LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);