diff --git a/src/emucore/elf/BusTransactionQueue.cxx b/src/emucore/elf/BusTransactionQueue.cxx index f6a3e53b5..dae5ae1a9 100644 --- a/src/emucore/elf/BusTransactionQueue.cxx +++ b/src/emucore/elf/BusTransactionQueue.cxx @@ -21,10 +21,10 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BusTransactionQueue::Transaction BusTransactionQueue::Transaction::transactionYield( - uInt16 address, uInt64 timestamp + uInt16 address, uInt64 timestamp, uInt16 mask ) { address &= 0x1fff; - return {.address = address, .value = 0, .timestamp = timestamp, .yield = true}; + return {.address = address, .mask = mask, .value = 0, .timestamp = timestamp, .yield = true}; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -32,7 +32,7 @@ BusTransactionQueue::Transaction BusTransactionQueue::Transaction::transactionDr uInt16 address, uInt8 value, uInt64 timestamp ) { address &= 0x1fff; - return {.address = address, .value = value, .timestamp = timestamp, .yield = false}; + return {.address = address, .mask = 0xffff, .value = value, .timestamp = timestamp, .yield = false}; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -112,9 +112,9 @@ BusTransactionQueue& BusTransactionQueue::stuffByte(uInt8 value, uInt16 address) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BusTransactionQueue& BusTransactionQueue::yield(uInt16 address) +BusTransactionQueue& BusTransactionQueue::yield(uInt16 address, uInt16 mask) { - push(Transaction::transactionYield(address, myTimestamp)); + push(Transaction::transactionYield(address, myTimestamp, mask)); return *this; } @@ -131,7 +131,10 @@ BusTransactionQueue::Transaction* BusTransactionQueue::getNextTransaction(uInt16 if (myQueueSize == 0) return nullptr; Transaction* nextTransaction = &myQueue[myQueueNext]; - if (nextTransaction->address != (address & 0x1fff) || nextTransaction->timestamp > timestamp) return nullptr; + if ( + nextTransaction->address != (address & 0x1fff & nextTransaction->mask) || + nextTransaction->timestamp > timestamp + ) return nullptr; myQueueNext = (myQueueNext + 1) % myQueueCapacity; myQueueSize--; diff --git a/src/emucore/elf/BusTransactionQueue.hxx b/src/emucore/elf/BusTransactionQueue.hxx index 795cdbfe3..bd4625171 100644 --- a/src/emucore/elf/BusTransactionQueue.hxx +++ b/src/emucore/elf/BusTransactionQueue.hxx @@ -23,12 +23,13 @@ class BusTransactionQueue { public: struct Transaction { - static Transaction transactionYield(uInt16 address, uInt64 timestamp); + static Transaction transactionYield(uInt16 address, uInt64 timestamp, uInt16 mask); static Transaction transactionDrive(uInt16 address, uInt8 value, uInt64 timestamp); void setBusState(bool& drive, uInt8& value) const; uInt16 address{0}; + uInt16 mask{0xffff}; uInt8 value{0}; uInt64 timestamp{0}; bool yield{false}; @@ -48,7 +49,7 @@ class BusTransactionQueue { BusTransactionQueue& injectROMAt(uInt8 value, uInt16 address); BusTransactionQueue& stuffByte(uInt8 value, uInt16 address); - BusTransactionQueue& yield(uInt16 address); + BusTransactionQueue& yield(uInt16 address, uInt16 mask = 0xffff); bool hasPendingTransaction() const; Transaction* getNextTransaction(uInt16 address, uInt64 timestamp); diff --git a/src/emucore/elf/VcsLib.cxx b/src/emucore/elf/VcsLib.cxx index 7c3171da4..86ecbd48c 100644 --- a/src/emucore/elf/VcsLib.cxx +++ b/src/emucore/elf/VcsLib.cxx @@ -176,6 +176,15 @@ void VcsLib::vcsLda2(uInt8 value) .injectROM(value); } +CortexM0::err_t VcsLib::stackOperation(uInt16& value, uInt8& op, uInt8 opcode) +{ + myTransactionQueue + .injectROM(opcode) + .yield(0, 0x1000); + + return returnFromStub(value, op); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, CortexM0& cortex) { @@ -244,7 +253,17 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex return returnFromStub(value, op); case ADDR_VCS_WRITE6: - FatalEmulationError::raise("unimplemented: vcsWrite6"); + arg = cortex.getRegister(0); + + myTransactionQueue + .injectROM(0xa9) + .injectROM(cortex.getRegister(1)) + .injectROM(0x8d) + .injectROM(arg) + .injectROM(arg >> 8) + .yield(arg); + + return returnFromStub(value, op); case ADDR_VCS_LDA2: vcsLda2(cortex.getRegister(0)); @@ -265,7 +284,14 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex return returnFromStub(value, op); case ADDR_VCS_SAX3: - FatalEmulationError::raise("unimplemented: vcsSax3"); + arg = cortex.getRegister(0); + + myTransactionQueue + .injectROM(0x87) + .injectROM(arg) + .yield(arg); + + return returnFromStub(value, op); case ADDR_VCS_STA3: arg = cortex.getRegister(0); @@ -371,22 +397,32 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex return returnFromStub(value, op); case ADDR_VCS_TXS2: - FatalEmulationError::raise("unimplemented: vcsTx2"); + myTransactionQueue.injectROM(0x9a); + return returnFromStub(value, op); case ADDR_VCS_JSR6: - FatalEmulationError::raise("unimplemented: vcsJsr6"); + arg = cortex.getRegister(0); + + myTransactionQueue + .injectROM(0x20) + .injectROM(arg) + .yield(0, 0x1000) + .injectROM(arg >> 8) + .setNextInjectAddress(arg & 0x1fff); + + return returnFromStub(value, op); case ADDR_VCS_PHA3: - FatalEmulationError::raise("unimplemented: vcsPha3"); + return stackOperation(value, op, 0x48); case ADDR_VCS_PHP3: - FatalEmulationError::raise("unimplemented: vcsPph3"); + return stackOperation(value, op, 0x08); case ADDR_VCS_PLA4: - FatalEmulationError::raise("unimplemented: vcsPla4"); + return stackOperation(value, op, 0x68); case ADDR_VCS_PLP4: - FatalEmulationError::raise("unimplemented: vcsPlp4"); + return stackOperation(value, op, 0x28); case ADDR_VCS_PLA4_EX: FatalEmulationError::raise("unimplemented: vcsPla4Ex"); @@ -395,7 +431,15 @@ CortexM0::err_t VcsLib::fetch16(uInt32 address, uInt16& value, uInt8& op, Cortex FatalEmulationError::raise("unimplemented: vcsPlp4Ex"); case ADDR_VCS_JMP_TO_RAM3: - FatalEmulationError::raise("unimplemented: vcsJmpToRam3"); + arg = cortex.getRegister(0); + + myTransactionQueue + .injectROM(0x4c) + .injectROM(arg) + .injectROM(arg >> 8) + .yield(arg); + + return returnFromStub(value, op); case ADDR_VCS_WAIT_FOR_ADDRESS: FatalEmulationError::raise("unimplemented: vcsWaitForAddress"); diff --git a/src/emucore/elf/VcsLib.hxx b/src/emucore/elf/VcsLib.hxx index f057818ca..02896effb 100644 --- a/src/emucore/elf/VcsLib.hxx +++ b/src/emucore/elf/VcsLib.hxx @@ -59,6 +59,8 @@ class VcsLib: public CortexM0::BusTransactionDelegate { return CortexM0::ERR_NONE; } + CortexM0::err_t stackOperation(uInt16& value, uInt8& op, uInt8 opcode); + private: BusTransactionQueue& myTransactionQueue;