diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index bab084a1c..4a44fe7be 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -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(...) { diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index d7fbbc7fb..ba6a74ef5 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -28,6 +28,8 @@ class Settings; +#include + #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; + 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++) diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index d5e39c830..9caf8741b 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -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(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index ad14fc9d9..18c47e1f2 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -401,6 +401,8 @@ class TIA : public Device void onFrameComplete(); + void onHalt(); + void updateEmulation(); void cycle(uInt32 colorClocks);