mirror of https://github.com/stella-emu/stella.git
Implement proper RDY emulation --- fixes #42.
This commit is contained in:
parent
048da2f6dd
commit
8d46679286
|
@ -58,7 +58,9 @@ M6502::M6502(const Settings& settings)
|
|||
myLastSrcAddressA(-1),
|
||||
myLastSrcAddressX(-1),
|
||||
myLastSrcAddressY(-1),
|
||||
myDataAddressForPoke(0)
|
||||
myDataAddressForPoke(0),
|
||||
myOnHaltCallback(0),
|
||||
myHaltRequested(false)
|
||||
{
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
myDebugger = nullptr;
|
||||
|
@ -102,11 +104,18 @@ void M6502::reset()
|
|||
myLastSrcAddressS = myLastSrcAddressA =
|
||||
myLastSrcAddressX = myLastSrcAddressY = -1;
|
||||
myDataAddressForPoke = 0;
|
||||
|
||||
myHaltRequested = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
inline uInt8 M6502::peek(uInt16 address, uInt8 flags)
|
||||
{
|
||||
if (myHaltRequested) {
|
||||
myOnHaltCallback();
|
||||
myHaltRequested = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// TODO - move this logic directly into CartAR
|
||||
if(address != myLastAddress)
|
||||
|
@ -159,6 +168,13 @@ inline void M6502::poke(uInt16 address, uInt8 value)
|
|||
myLastPokeAddress = address;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6502::requestHalt()
|
||||
{
|
||||
if (!myOnHaltCallback) throw runtime_error("onHaltCallback not configured");
|
||||
myHaltRequested = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502::execute(uInt32 number)
|
||||
{
|
||||
|
@ -310,6 +326,8 @@ bool M6502::save(Serializer& out) const
|
|||
out.putInt(myLastSrcAddressA);
|
||||
out.putInt(myLastSrcAddressX);
|
||||
out.putInt(myLastSrcAddressY);
|
||||
|
||||
out.putBool(myHaltRequested);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -358,6 +376,8 @@ bool M6502::load(Serializer& in)
|
|||
myLastSrcAddressA = in.getInt();
|
||||
myLastSrcAddressX = in.getInt();
|
||||
myLastSrcAddressY = in.getInt();
|
||||
|
||||
myHaltRequested = in.getBool();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
class Settings;
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "System.hxx"
|
||||
#include "Serializable.hxx"
|
||||
|
@ -50,6 +52,10 @@ class M6502 : public Serializable
|
|||
friend class CartDebug;
|
||||
friend class CpuDebug;
|
||||
|
||||
public:
|
||||
|
||||
using onHaltCallback = std::function<void()>;
|
||||
|
||||
public:
|
||||
/**
|
||||
Create a new 6502 microprocessor.
|
||||
|
@ -83,6 +89,21 @@ class M6502 : public Serializable
|
|||
*/
|
||||
void nmi() { myExecutionStatus |= NonmaskableInterruptBit; }
|
||||
|
||||
/**
|
||||
Set the callback for handling a halt condition
|
||||
*/
|
||||
void setOnHaltCallback(onHaltCallback callback) { myOnHaltCallback = callback; }
|
||||
|
||||
/**
|
||||
RDY pulled low --- halt on next read.
|
||||
*/
|
||||
void requestHalt();
|
||||
|
||||
/**
|
||||
Pull RDY high again before the callback was triggered.
|
||||
*/
|
||||
void clearHaltRequest() { myHaltRequested = false; };
|
||||
|
||||
/**
|
||||
Execute instructions until the specified number of instructions
|
||||
is executed, someone stops execution, or an error occurs. Answers
|
||||
|
@ -328,6 +349,12 @@ class M6502 : public Serializable
|
|||
/// Indicates the number of system cycles per processor cycle
|
||||
static constexpr uInt32 SYSTEM_CYCLES_PER_CPU = 1;
|
||||
|
||||
/// Called when the processor enters halt state
|
||||
onHaltCallback myOnHaltCallback;
|
||||
|
||||
/// Indicates whether RDY was pulled low
|
||||
bool myHaltRequested;
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
Int32 evalCondBreaks() {
|
||||
for(uInt32 i = 0; i < myBreakConds.size(); i++)
|
||||
|
|
|
@ -186,6 +186,12 @@ void TIA::installDelegate(System& system, Device& device)
|
|||
for(uInt32 i = 0; i < 8192; i += (1 << System::PAGE_SHIFT))
|
||||
if((i & 0x1080) == 0x0000)
|
||||
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
|
||||
|
||||
mySystem->m6502().setOnHaltCallback(
|
||||
[this] () {
|
||||
onHalt();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -428,17 +434,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
|||
switch (address)
|
||||
{
|
||||
case WSYNC:
|
||||
// It appears that the 6507 only halts during a read cycle so
|
||||
// we test here for follow-on writes which should be ignored as
|
||||
// far as halting the processor is concerned.
|
||||
// See issue #42 for more information.
|
||||
if (mySystem->m6502().lastAccessWasRead())
|
||||
{
|
||||
mySubClock += (228 - myHctr) % 228;
|
||||
mySystem->incrementCycles(mySubClock / 3);
|
||||
mySubClock %= 3;
|
||||
}
|
||||
myShadowRegisters[address] = value;
|
||||
mySystem->m6502().requestHalt();
|
||||
break;
|
||||
|
||||
case RSYNC:
|
||||
|
@ -1050,6 +1046,14 @@ void TIA::onFrameComplete()
|
|||
myConsole.setFramerate(myFrameManager.frameRate());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::onHalt()
|
||||
{
|
||||
mySubClock += (228 - myHctr) % 228;
|
||||
mySystem->incrementCycles(mySubClock / 3);
|
||||
mySubClock %= 3;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::cycle(uInt32 colorClocks)
|
||||
{
|
||||
|
@ -1161,6 +1165,8 @@ void TIA::nextLine()
|
|||
myFrameManager.nextLine();
|
||||
|
||||
if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache();
|
||||
|
||||
mySystem->m6502().clearHaltRequest();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -401,6 +401,8 @@ class TIA : public Device
|
|||
|
||||
void onFrameComplete();
|
||||
|
||||
void onHalt();
|
||||
|
||||
void updateEmulation();
|
||||
|
||||
void cycle(uInt32 colorClocks);
|
||||
|
|
Loading…
Reference in New Issue