DS Timers: Fix ARM9 timers running too fast

This commit is contained in:
Vicki Pfau 2017-04-25 16:14:08 -07:00
parent 6265ff20bd
commit 6d3764d800
4 changed files with 10 additions and 4 deletions

View File

@ -25,6 +25,7 @@ Bugfixes:
- DS Audio: Fix audio sampling slightly too quickly - DS Audio: Fix audio sampling slightly too quickly
- Feature: Fix resizing GIF buffer (fixes mgba.io/i/695) - Feature: Fix resizing GIF buffer (fixes mgba.io/i/695)
- DS GX: Retain translucent polygon ID when drawing opaque fragments (fixes mgba.io/i/661) - DS GX: Retain translucent polygon ID when drawing opaque fragments (fixes mgba.io/i/661)
- DS Timers: Fix ARM9 timers running too fast
Misc: Misc:
- DS: Set boot complete bit in RAM on boot (fixes mgba.io/i/576, mgba.io/i/580, mgba.io/i/586) - DS: Set boot complete bit in RAM on boot (fixes mgba.io/i/576, mgba.io/i/580, mgba.io/i/586)
- DS Memory: Ensure DS9 I/O is 8-byte aligned - DS Memory: Ensure DS9 I/O is 8-byte aligned

View File

@ -25,6 +25,7 @@ struct GBATimer {
struct mTimingEvent event; struct mTimingEvent event;
int32_t overflowInterval; int32_t overflowInterval;
GBATimerFlags flags; GBATimerFlags flags;
int forcedPrescale;
}; };
struct ARMCore; struct ARMCore;

View File

@ -71,18 +71,22 @@ void DSTimerInit(struct DS* ds) {
ds->ds9.timers[0].event.callback = DSTimerUpdate0; ds->ds9.timers[0].event.callback = DSTimerUpdate0;
ds->ds9.timers[0].event.context = &ds->ds9; ds->ds9.timers[0].event.context = &ds->ds9;
ds->ds9.timers[0].event.priority = 0x20; ds->ds9.timers[0].event.priority = 0x20;
ds->ds9.timers[0].forcedPrescale = 1;
ds->ds9.timers[1].event.name = "DS9 Timer 1"; ds->ds9.timers[1].event.name = "DS9 Timer 1";
ds->ds9.timers[1].event.callback = DSTimerUpdate1; ds->ds9.timers[1].event.callback = DSTimerUpdate1;
ds->ds9.timers[1].event.context = &ds->ds9; ds->ds9.timers[1].event.context = &ds->ds9;
ds->ds9.timers[1].event.priority = 0x21; ds->ds9.timers[1].event.priority = 0x21;
ds->ds9.timers[1].forcedPrescale = 1;
ds->ds9.timers[2].event.name = "DS9 Timer 2"; ds->ds9.timers[2].event.name = "DS9 Timer 2";
ds->ds9.timers[2].event.callback = DSTimerUpdate2; ds->ds9.timers[2].event.callback = DSTimerUpdate2;
ds->ds9.timers[2].event.context = &ds->ds9; ds->ds9.timers[2].event.context = &ds->ds9;
ds->ds9.timers[2].event.priority = 0x22; ds->ds9.timers[2].event.priority = 0x22;
ds->ds9.timers[2].forcedPrescale = 1;
ds->ds9.timers[3].event.name = "DS9 Timer 3"; ds->ds9.timers[3].event.name = "DS9 Timer 3";
ds->ds9.timers[3].event.callback = DSTimerUpdate3; ds->ds9.timers[3].event.callback = DSTimerUpdate3;
ds->ds9.timers[3].event.context = &ds->ds9; ds->ds9.timers[3].event.context = &ds->ds9;
ds->ds9.timers[3].event.priority = 0x23; ds->ds9.timers[3].event.priority = 0x23;
ds->ds9.timers[3].forcedPrescale = 1;
} }
void DSTimerWriteTMCNT_HI(struct GBATimer* timer, struct mTiming* timing, struct ARMCore* cpu, uint16_t* io, uint16_t value) { void DSTimerWriteTMCNT_HI(struct GBATimer* timer, struct mTiming* timing, struct ARMCore* cpu, uint16_t* io, uint16_t value) {

View File

@ -128,16 +128,16 @@ void GBATimerWriteTMCNT_HI(struct GBATimer* timer, struct mTiming* timing, struc
unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(timer->flags); unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(timer->flags);
switch (control & 0x0003) { switch (control & 0x0003) {
case 0x0000: case 0x0000:
timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 0); timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, timer->forcedPrescale);
break; break;
case 0x0001: case 0x0001:
timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 6); timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 6 + timer->forcedPrescale);
break; break;
case 0x0002: case 0x0002:
timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 8); timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 8 + timer->forcedPrescale);
break; break;
case 0x0003: case 0x0003:
timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 10); timer->flags = GBATimerFlagsSetPrescaleBits(timer->flags, 10 + timer->forcedPrescale);
break; break;
} }
timer->flags = GBATimerFlagsTestFillCountUp(timer->flags, timer > 0 && (control & 0x0004)); timer->flags = GBATimerFlagsTestFillCountUp(timer->flags, timer > 0 && (control & 0x0004));