Bus snooping.

This commit is contained in:
Christian Speckner 2024-07-29 18:56:12 +02:00
parent ba75f72826
commit f4b25da4cd
4 changed files with 55 additions and 8 deletions

View File

@ -330,7 +330,9 @@ inline uInt8 CartridgeELF::driveBus(uInt16 address, uInt8 value)
if (myIsBusDriven) value |= myDriveBusValue; if (myIsBusDriven) value |= myDriveBusValue;
runArm(); myVcsLib.updateBus(address, value);
if (!myVcsLib.isSuspended()) runArm();
return value; return value;
} }
@ -493,7 +495,7 @@ void CartridgeELF::runArm()
const CortexM0::err_t err = myCortexEmu.run(cyclesGoal, cycles); const CortexM0::err_t err = myCortexEmu.run(cyclesGoal, cycles);
if (err && (CortexM0::getErrCustom(err) != ERR_QUEUE_FULL)) if (err && (CortexM0::getErrCustom(err) != ERR_STOP_EXECUTION))
FatalEmulationError::raise("error executing ARM code: " + CortexM0::describeError(err)); FatalEmulationError::raise("error executing ARM code: " + CortexM0::describeError(err));
} }

View File

@ -112,7 +112,8 @@ namespace elfEnvironment {
constexpr uInt32 RETURN_ADDR_MAIN = 0xffffdead; constexpr uInt32 RETURN_ADDR_MAIN = 0xffffdead;
constexpr uInt32 ERR_QUEUE_FULL = 1; constexpr uInt32 ERR_STOP_EXECUTION = 1;
constexpr uInt32 QUEUE_SIZE_LIMIT = 10; constexpr uInt32 QUEUE_SIZE_LIMIT = 10;
enum class Palette: uInt8 {pal, ntsc}; enum class Palette: uInt8 {pal, ntsc};

View File

@ -60,6 +60,10 @@ VcsLib::VcsLib(BusTransactionQueue& transactionQueue) : myTransactionQueue(trans
void VcsLib::reset() void VcsLib::reset()
{ {
myStuffMaskA = myStuffMaskX = myStuffMaskY = 0x00; myStuffMaskA = myStuffMaskX = myStuffMaskY = 0x00;
myIsWaitingForRead = false;
myWaitingForReadAddress = 0;
myCurrentAddress = 0;
myCurrentValue = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -124,7 +128,7 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
CortexM0::err_t err; CortexM0::err_t err;
if (myTransactionQueue.size() >= elfEnvironment::QUEUE_SIZE_LIMIT) if (myTransactionQueue.size() >= elfEnvironment::QUEUE_SIZE_LIMIT)
return CortexM0::errCustom(ERR_QUEUE_FULL); return CortexM0::errCustom(ERR_STOP_EXECUTION);
myTransactionQueue.setTimestamp(cortex.getCycles()); myTransactionQueue.setTimestamp(cortex.getCycles());
@ -170,7 +174,8 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
return returnFromStub(value, op); return returnFromStub(value, op);
case ADDR_VCS_NOP2: case ADDR_VCS_NOP2:
FatalEmulationError::raise("unimplemented: vcsNop2"); myTransactionQueue.injectROM(0xea);
return returnFromStub(value, op);
case ADDR_VCS_NOP2N: case ADDR_VCS_NOP2N:
vcsNop2n(cortex.getRegister(0)); vcsNop2n(cortex.getRegister(0));
@ -234,7 +239,28 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
return returnFromStub(value, op); return returnFromStub(value, op);
case ADDR_VCS_READ4: case ADDR_VCS_READ4:
FatalEmulationError::raise("unimplemented: vcsRead4"); if (myIsWaitingForRead) {
if (myTransactionQueue.size() > 0 || myCurrentAddress != myWaitingForReadAddress)
return CortexM0::errCustom(ERR_STOP_EXECUTION);
myIsWaitingForRead = false;
cortex.setRegister(0, myCurrentValue);
return returnFromStub(value, op);
} else {
arg = cortex.getRegister(0);
myIsWaitingForRead = true;
myWaitingForReadAddress = arg;
myTransactionQueue
.injectROM(0xad)
.injectROM(arg & 0xff)
.injectROM(arg >> 8)
.yield(arg);
return CortexM0::errCustom(ERR_STOP_EXECUTION);
}
case ADDR_RANDINT: case ADDR_RANDINT:
FatalEmulationError::raise("unimplemented: randint "); FatalEmulationError::raise("unimplemented: randint ");
@ -277,6 +303,12 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex
} }
} }
void VcsLib::updateBus(uInt16 address, uInt8 value)
{
myCurrentAddress = address;
myCurrentValue = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CortexM0::err_t VcsLib::returnFromStub(uInt16& value, uInt8& op) CortexM0::err_t VcsLib::returnFromStub(uInt16& value, uInt8& op)
{ {

View File

@ -20,8 +20,7 @@
#include "bspf.hxx" #include "bspf.hxx"
#include "CortexM0.hxx" #include "CortexM0.hxx"
#include "BusTransactionQueue.hxx"
class BusTransactionQueue;
class VcsLib: public CortexM0::BusTransactionDelegate { class VcsLib: public CortexM0::BusTransactionDelegate {
public: public:
@ -31,6 +30,13 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override; CortexM0::err_t fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) override;
void updateBus(uInt16 address, uInt8 value);
inline bool isSuspended() const {
return
myIsWaitingForRead && (myTransactionQueue.size() > 0 || (myWaitingForReadAddress != myCurrentAddress));
}
void vcsWrite5(uInt8 zpAddress, uInt8 value); void vcsWrite5(uInt8 zpAddress, uInt8 value);
void vcsCopyOverblankToRiotRam(); void vcsCopyOverblankToRiotRam();
void vcsStartOverblank(); void vcsStartOverblank();
@ -48,6 +54,12 @@ class VcsLib: public CortexM0::BusTransactionDelegate {
uInt8 myStuffMaskX{0x00}; uInt8 myStuffMaskX{0x00};
uInt8 myStuffMaskY{0x00}; uInt8 myStuffMaskY{0x00};
bool myIsWaitingForRead{false};
uInt16 myWaitingForReadAddress{0};
uInt16 myCurrentAddress{0};
uInt8 myCurrentValue{0};
private: private:
VcsLib(const VcsLib&) = delete; VcsLib(const VcsLib&) = delete;
VcsLib(VcsLib&&) = delete; VcsLib(VcsLib&&) = delete;