Fix reads and writes during timer wrap. Fixes #606 .

This commit is contained in:
Christian Speckner 2020-06-17 00:20:26 +02:00
parent e1e9c61bc6
commit f1998c761c
2 changed files with 9 additions and 12 deletions

View File

@ -59,7 +59,6 @@ void M6532::reset()
myTimer = mySystem->randGenerator().next() & 0xff; myTimer = mySystem->randGenerator().next() & 0xff;
myDivider = 1024; myDivider = 1024;
mySubTimer = 0; mySubTimer = 0;
myTimerWrapped = false;
myWrappedThisCycle = false; myWrappedThisCycle = false;
mySetTimerCycle = myLastCycle = 0; mySetTimerCycle = myLastCycle = 0;
@ -121,16 +120,16 @@ void M6532::updateEmulation()
myWrappedThisCycle = false; myWrappedThisCycle = false;
mySubTimer = (cycles + mySubTimer) % myDivider; mySubTimer = (cycles + mySubTimer) % myDivider;
if(!myTimerWrapped) if ((myInterruptFlag & TimerBit) == 0)
{ {
uInt32 timerTicks = (cycles + subTimer) / myDivider; uInt32 timerTicks = (cycles + subTimer) / myDivider;
if(timerTicks > myTimer) if(timerTicks > myTimer)
{ {
cycles -= ((myTimer + 1) * myDivider - subTimer); cycles -= ((myTimer + 1) * myDivider - subTimer);
myWrappedThisCycle = cycles == 0; myWrappedThisCycle = cycles == 0;
myTimer = 0xFF; myTimer = 0xFF;
myTimerWrapped = true;
myInterruptFlag |= TimerBit; myInterruptFlag |= TimerBit;
} }
else else
@ -140,8 +139,10 @@ void M6532::updateEmulation()
} }
} }
if(myTimerWrapped) if((myInterruptFlag & TimerBit) != 0) {
myTimer = (myTimer - cycles) & 0xFF; myTimer = (myTimer - cycles) & 0xFF;
myWrappedThisCycle = myTimer == 0xFF;
}
myLastCycle = mySystem->cycles(); myLastCycle = mySystem->cycles();
} }
@ -219,7 +220,7 @@ uInt8 M6532::peek(uInt16 addr)
{ {
// Timer Flag is always cleared when accessing INTIM // Timer Flag is always cleared when accessing INTIM
if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit; if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit;
myTimerWrapped = false;
return myTimer; return myTimer;
} }
@ -312,10 +313,9 @@ void M6532::setTimerRegister(uInt8 value, uInt8 interval)
myTimer = value; myTimer = value;
mySubTimer = myDivider - 1; mySubTimer = myDivider - 1;
myTimerWrapped = false;
// Interrupt timer flag is cleared (and invalid) when writing to the timer // Interrupt timer flag is cleared (and invalid) when writing to the timer
myInterruptFlag &= ~TimerBit; if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit;
mySetTimerCycle = mySystem->cycles(); mySetTimerCycle = mySystem->cycles();
} }
@ -364,7 +364,6 @@ bool M6532::save(Serializer& out) const
out.putInt(myTimer); out.putInt(myTimer);
out.putInt(mySubTimer); out.putInt(mySubTimer);
out.putInt(myDivider); out.putInt(myDivider);
out.putBool(myTimerWrapped);
out.putBool(myWrappedThisCycle); out.putBool(myWrappedThisCycle);
out.putLong(myLastCycle); out.putLong(myLastCycle);
out.putLong(mySetTimerCycle); out.putLong(mySetTimerCycle);
@ -397,7 +396,6 @@ bool M6532::load(Serializer& in)
myTimer = in.getInt(); myTimer = in.getInt();
mySubTimer = in.getInt(); mySubTimer = in.getInt();
myDivider = in.getInt(); myDivider = in.getInt();
myTimerWrapped = in.getBool();
myWrappedThisCycle = in.getBool(); myWrappedThisCycle = in.getBool();
myLastCycle = in.getLong(); myLastCycle = in.getLong();
mySetTimerCycle = in.getLong(); mySetTimerCycle = in.getLong();
@ -446,7 +444,7 @@ Int32 M6532::intimClocks()
// INTIM value, it will give the current number of clocks between one // INTIM value, it will give the current number of clocks between one
// INTIM value and the next // INTIM value and the next
return myTimerWrapped ? 1 : (myDivider - mySubTimer); return ((myInterruptFlag & TimerBit) != 0) ? 1 : (myDivider - mySubTimer);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -196,8 +196,7 @@ class M6532 : public Device
// The divider // The divider
uInt32 myDivider{1}; uInt32 myDivider{1};
// Has the timer wrapped? // Has the timer wrapped this very cycle?
bool myTimerWrapped{false};
bool myWrappedThisCycle{false}; bool myWrappedThisCycle{false};
// Cycle when the timer set. Debugging only. // Cycle when the timer set. Debugging only.