Implement proper RDY emulation --- fixes #42.

This commit is contained in:
Christian Speckner 2017-05-27 01:00:03 +02:00
parent 048da2f6dd
commit 8d46679286
4 changed files with 67 additions and 12 deletions

View File

@ -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(...)
{

View File

@ -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++)

View File

@ -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();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -401,6 +401,8 @@ class TIA : public Device
void onFrameComplete();
void onHalt();
void updateEmulation();
void cycle(uInt32 colorClocks);