mirror of https://github.com/stella-emu/stella.git
Some improvements to RIOT handling of INTIM and TIMINT behaviour,
particularly in edge cases. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2551 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
f3d5beb3d6
commit
06854e7877
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#define STELLA_VERSION "3.7.3_svn"
|
#define STELLA_VERSION "3.8_pre1"
|
||||||
#define STELLA_BUILD atoi("$Rev$" + 6)
|
#define STELLA_BUILD atoi("$Rev$" + 6)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
|
|
||||||
#include "M6532.hxx"
|
#include "M6532.hxx"
|
||||||
|
|
||||||
#define TIMER_BIT 0x80
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
M6532::M6532(const Console& console, const Settings& settings)
|
M6532::M6532(const Console& console, const Settings& settings)
|
||||||
: myConsole(console),
|
: myConsole(console),
|
||||||
|
@ -63,8 +61,9 @@ void M6532::reset()
|
||||||
// Zero the timer registers
|
// Zero the timer registers
|
||||||
myOutTimer[0] = myOutTimer[1] = myOutTimer[2] = myOutTimer[3] = 0x00;
|
myOutTimer[0] = myOutTimer[1] = myOutTimer[2] = myOutTimer[3] = 0x00;
|
||||||
|
|
||||||
// Zero the interrupt flag register
|
// Zero the interrupt flag register and mark D7 as invalid
|
||||||
myInterruptFlag = 0x00;
|
myInterruptFlag = 0x00;
|
||||||
|
myTimerFlagValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -147,18 +146,41 @@ uInt8 M6532::peek(uInt16 addr)
|
||||||
return myDDRB;
|
return myDDRB;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x04: // Timer Output
|
case 0x04: // INTIM - Timer Output
|
||||||
case 0x06:
|
case 0x06:
|
||||||
{
|
{
|
||||||
// Update timer state and return the resulting clock
|
// Timer Flag is always cleared when accessing INTIM
|
||||||
return updateTimer();
|
myInterruptFlag &= ~TimerBit;
|
||||||
|
|
||||||
|
// Get number of clocks since timer was set
|
||||||
|
Int32 timer = timerClocks();
|
||||||
|
if(timer >= 0)
|
||||||
|
{
|
||||||
|
// Return at 'divide by TIMxT' interval rate
|
||||||
|
return (timer >> myIntervalShift) & 0xff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return at 'divide by 1' rate
|
||||||
|
uInt8 divByOne = timer & 0xff;
|
||||||
|
|
||||||
|
// Timer flag has been updated; don't update it again on TIMINT read
|
||||||
|
if(divByOne != 0 && divByOne != 255)
|
||||||
|
myTimerFlagValid = true;
|
||||||
|
|
||||||
|
return divByOne;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x05: // Interrupt Flag
|
case 0x05: // TIMINT/INSTAT - Interrupt Flag
|
||||||
case 0x07:
|
case 0x07:
|
||||||
{
|
{
|
||||||
// Update timer state and return the resulting flag(s)
|
// Update timer flag if it is invalid and timer has expired
|
||||||
updateTimer();
|
if(!myTimerFlagValid && timerClocks() < 0)
|
||||||
|
{
|
||||||
|
myInterruptFlag |= TimerBit;
|
||||||
|
myTimerFlagValid = true;
|
||||||
|
}
|
||||||
return myInterruptFlag;
|
return myInterruptFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +210,7 @@ bool M6532::poke(uInt16 addr, uInt8 value)
|
||||||
// A2 distinguishes I/O registers from the timer
|
// A2 distinguishes I/O registers from the timer
|
||||||
if((addr & 0x04) != 0)
|
if((addr & 0x04) != 0)
|
||||||
{
|
{
|
||||||
if((addr & 0x10) != 0)
|
if((addr & 0x10) != 0) // TIMxT (x = 1, 8, 64, 1024)
|
||||||
setTimerRegister(value, addr & 0x03);
|
setTimerRegister(value, addr & 0x03);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -235,8 +257,9 @@ void M6532::setTimerRegister(uInt8 value, uInt8 interval)
|
||||||
myTimer = value << myIntervalShift;
|
myTimer = value << myIntervalShift;
|
||||||
myCyclesWhenTimerSet = mySystem->cycles();
|
myCyclesWhenTimerSet = mySystem->cycles();
|
||||||
|
|
||||||
// Interrupt timer flag is reset when writing to the timer
|
// Interrupt timer flag is cleared (and invalid) when writing to the timer
|
||||||
myInterruptFlag &= ~TIMER_BIT;
|
myInterruptFlag &= ~TimerBit;
|
||||||
|
myTimerFlagValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -273,32 +296,6 @@ void M6532::setPinState(bool swcha)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 M6532::updateTimer()
|
|
||||||
{
|
|
||||||
// Get number of clocks since timer was set
|
|
||||||
Int32 timer = timerClocks();
|
|
||||||
|
|
||||||
if(timer >= 0)
|
|
||||||
{
|
|
||||||
// Timer hasn't expired yet
|
|
||||||
myInterruptFlag &= ~TIMER_BIT;
|
|
||||||
|
|
||||||
return (timer >> myIntervalShift) & 0xff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Timer has expired, set flag
|
|
||||||
myInterruptFlag |= TIMER_BIT;
|
|
||||||
|
|
||||||
// According to the M6532 documentation, the timer continues to count
|
|
||||||
// down to -255 timer clocks after wraparound. However, it isn't
|
|
||||||
// entirely clear what happens *after* if reaches -255.
|
|
||||||
// For now, we'll let it continuously wrap around.
|
|
||||||
return timer & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool M6532::save(Serializer& out) const
|
bool M6532::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
|
@ -318,6 +315,7 @@ bool M6532::save(Serializer& out) const
|
||||||
out.putByte(myOutA);
|
out.putByte(myOutA);
|
||||||
out.putByte(myOutB);
|
out.putByte(myOutB);
|
||||||
out.putByte(myInterruptFlag);
|
out.putByte(myInterruptFlag);
|
||||||
|
out.putBool(myTimerFlagValid);
|
||||||
out.putByteArray(myOutTimer, 4);
|
out.putByteArray(myOutTimer, 4);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
|
@ -349,6 +347,7 @@ bool M6532::load(Serializer& in)
|
||||||
myOutA = in.getByte();
|
myOutA = in.getByte();
|
||||||
myOutB = in.getByte();
|
myOutB = in.getByte();
|
||||||
myInterruptFlag = in.getByte();
|
myInterruptFlag = in.getByte();
|
||||||
|
myTimerFlagValid = in.getBool();
|
||||||
in.getByteArray(myOutTimer, 4);
|
in.getByteArray(myOutTimer, 4);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
|
|
|
@ -143,9 +143,15 @@ class M6532 : public Device
|
||||||
|
|
||||||
void setTimerRegister(uInt8 data, uInt8 interval);
|
void setTimerRegister(uInt8 data, uInt8 interval);
|
||||||
void setPinState(bool shcha);
|
void setPinState(bool shcha);
|
||||||
uInt8 updateTimer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Accessible bits in the interrupt flag register
|
||||||
|
// All other bits are always zeroed
|
||||||
|
enum {
|
||||||
|
TimerBit = 0x80,
|
||||||
|
PA7Bit = 0x40
|
||||||
|
};
|
||||||
|
|
||||||
// Reference to the console
|
// Reference to the console
|
||||||
const Console& myConsole;
|
const Console& myConsole;
|
||||||
|
|
||||||
|
@ -179,6 +185,10 @@ class M6532 : public Device
|
||||||
// Interrupt Flag Register
|
// Interrupt Flag Register
|
||||||
uInt8 myInterruptFlag;
|
uInt8 myInterruptFlag;
|
||||||
|
|
||||||
|
// Whether the timer flag (as currently set) can be used
|
||||||
|
// If it isn't valid, it will be updated as required
|
||||||
|
bool myTimerFlagValid;
|
||||||
|
|
||||||
// Last value written to the timer registers
|
// Last value written to the timer registers
|
||||||
uInt8 myOutTimer[4];
|
uInt8 myOutTimer[4];
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
|
|
||||||
#define STATE_HEADER "03070101state"
|
#define STATE_HEADER "03070102state"
|
||||||
#define MOVIE_HEADER "03030000movie"
|
#define MOVIE_HEADER "03030000movie"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
Loading…
Reference in New Issue