This commit is contained in:
Stephen Anthony 2017-05-27 14:10:35 -02:30
commit ea7a20a5a0
5 changed files with 69 additions and 12 deletions

View File

@ -21,6 +21,8 @@
- YStart autodetection - YStart autodetection
- ... - ...
* Proper emulation of RDY during write cycles.
* Much improved RIOT timer emulation never before seen in any emulator. * Much improved RIOT timer emulation never before seen in any emulator.
Special thanks to DirtyHairy for the implementation, and alex_79 for Special thanks to DirtyHairy for the implementation, and alex_79 for
finding documentation that finally describes in more detail how the finding documentation that finally describes in more detail how the

View File

@ -58,7 +58,9 @@ M6502::M6502(const Settings& settings)
myLastSrcAddressA(-1), myLastSrcAddressA(-1),
myLastSrcAddressX(-1), myLastSrcAddressX(-1),
myLastSrcAddressY(-1), myLastSrcAddressY(-1),
myDataAddressForPoke(0) myDataAddressForPoke(0),
myOnHaltCallback(0),
myHaltRequested(false)
{ {
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
myDebugger = nullptr; myDebugger = nullptr;
@ -102,11 +104,18 @@ void M6502::reset()
myLastSrcAddressS = myLastSrcAddressA = myLastSrcAddressS = myLastSrcAddressA =
myLastSrcAddressX = myLastSrcAddressY = -1; myLastSrcAddressX = myLastSrcAddressY = -1;
myDataAddressForPoke = 0; myDataAddressForPoke = 0;
myHaltRequested = false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline uInt8 M6502::peek(uInt16 address, uInt8 flags) inline uInt8 M6502::peek(uInt16 address, uInt8 flags)
{ {
if (myHaltRequested) {
myOnHaltCallback();
myHaltRequested = false;
}
//////////////////////////////////////////////// ////////////////////////////////////////////////
// TODO - move this logic directly into CartAR // TODO - move this logic directly into CartAR
if(address != myLastAddress) if(address != myLastAddress)
@ -159,6 +168,13 @@ inline void M6502::poke(uInt16 address, uInt8 value)
myLastPokeAddress = address; myLastPokeAddress = address;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::requestHalt()
{
if (!myOnHaltCallback) throw runtime_error("onHaltCallback not configured");
myHaltRequested = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502::execute(uInt32 number) bool M6502::execute(uInt32 number)
{ {
@ -310,6 +326,8 @@ bool M6502::save(Serializer& out) const
out.putInt(myLastSrcAddressA); out.putInt(myLastSrcAddressA);
out.putInt(myLastSrcAddressX); out.putInt(myLastSrcAddressX);
out.putInt(myLastSrcAddressY); out.putInt(myLastSrcAddressY);
out.putBool(myHaltRequested);
} }
catch(...) catch(...)
{ {
@ -358,6 +376,8 @@ bool M6502::load(Serializer& in)
myLastSrcAddressA = in.getInt(); myLastSrcAddressA = in.getInt();
myLastSrcAddressX = in.getInt(); myLastSrcAddressX = in.getInt();
myLastSrcAddressY = in.getInt(); myLastSrcAddressY = in.getInt();
myHaltRequested = in.getBool();
} }
catch(...) catch(...)
{ {

View File

@ -28,6 +28,8 @@
class Settings; class Settings;
#include <functional>
#include "bspf.hxx" #include "bspf.hxx"
#include "System.hxx" #include "System.hxx"
#include "Serializable.hxx" #include "Serializable.hxx"
@ -50,6 +52,10 @@ class M6502 : public Serializable
friend class CartDebug; friend class CartDebug;
friend class CpuDebug; friend class CpuDebug;
public:
using onHaltCallback = std::function<void()>;
public: public:
/** /**
Create a new 6502 microprocessor. Create a new 6502 microprocessor.
@ -83,6 +89,21 @@ class M6502 : public Serializable
*/ */
void nmi() { myExecutionStatus |= NonmaskableInterruptBit; } 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 Execute instructions until the specified number of instructions
is executed, someone stops execution, or an error occurs. Answers 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 /// Indicates the number of system cycles per processor cycle
static constexpr uInt32 SYSTEM_CYCLES_PER_CPU = 1; 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 #ifdef DEBUGGER_SUPPORT
Int32 evalCondBreaks() { Int32 evalCondBreaks() {
for(uInt32 i = 0; i < myBreakConds.size(); i++) 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)) for(uInt32 i = 0; i < 8192; i += (1 << System::PAGE_SHIFT))
if((i & 0x1080) == 0x0000) if((i & 0x1080) == 0x0000)
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access); 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) switch (address)
{ {
case WSYNC: case WSYNC:
// It appears that the 6507 only halts during a read cycle so mySystem->m6502().requestHalt();
// 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;
break; break;
case RSYNC: case RSYNC:
@ -1050,6 +1046,14 @@ void TIA::onFrameComplete()
myConsole.setFramerate(myFrameManager.frameRate()); myConsole.setFramerate(myFrameManager.frameRate());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::onHalt()
{
mySubClock += (228 - myHctr) % 228;
mySystem->incrementCycles(mySubClock / 3);
mySubClock %= 3;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::cycle(uInt32 colorClocks) void TIA::cycle(uInt32 colorClocks)
{ {
@ -1161,6 +1165,8 @@ void TIA::nextLine()
myFrameManager.nextLine(); myFrameManager.nextLine();
if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache(); if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache();
mySystem->m6502().clearHaltRequest();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

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