mirror of https://github.com/stella-emu/stella.git
Fix reads and writes during timer wrap. Fixes #606 .
This commit is contained in:
parent
e1e9c61bc6
commit
f1998c761c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue