diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index a9eee1d..3d21402 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -65,24 +65,24 @@ namespace ComSquare::CPU } } - unsigned DMA::_writeOneByte() + unsigned DMA::_writeOneByte(uint24_t aAddress, uint24_t bAddress) { // Address $2180 refers to the WRam data register. Write to/Read from this port when the a address is on the vram cause different behaviors. if (this->port == 0x80) { - auto accessor = this->_bus->getAccessor(this->aAddress.raw); + auto accessor = this->_bus->getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { if (this->controlRegister.direction == AToB) return 8; - this->_bus->write(this->aAddress.raw, 0xFF); + this->_bus->write(aAddress, 0xFF); return 4; } } if (this->controlRegister.direction == AToB) { - uint8_t data = this->_bus->read(this->aAddress.raw); - this->_bus->write(0x2100 | this->port, data); + uint8_t data = this->_bus->read(aAddress); + this->_bus->write(bAddress, data); } else { - uint8_t data = this->_bus->read(0x2100 | this->port); - this->_bus->write(this->aAddress.raw, data); + uint8_t data = this->_bus->read(bAddress); + this->_bus->write(aAddress, data); } return 8; } @@ -90,14 +90,33 @@ namespace ComSquare::CPU uint8_t DMA::run(unsigned int maxCycles) { unsigned cycles = 8; + int i = 0; do { - cycles += this->_writeOneByte(); + cycles += this->_writeOneByte(this->aAddress.raw, 0x2100 | this->port + this->getModeOffset(i)); if (!this->controlRegister.fixed) this->aAddress.page += this->controlRegister.increment ? -1 : 1; this->count.raw--; + i++; } while (this->count.raw > 0 && cycles < maxCycles); this->enabled = false; return cycles; } + + int DMA::getModeOffset(int index) + { + switch (this->controlRegister.mode) { + case OneToOne: + return 0; + case TwoToTwo: + return index % 2; + case TwoToOne: + return 0; + case FourToTwo: + return (index & 0b11) > 1; + case FourToFour: + return (index & 0b11); + } + return 0; + } } \ No newline at end of file diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index da9e8be..1daaf86 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -36,7 +36,9 @@ namespace ComSquare::CPU private: //! @brief Write one byte using the A address, the port and the direction. Handle special cases where no write occurs. //! @return The number of cycles used. - unsigned _writeOneByte(); + unsigned _writeOneByte(uint24_t aAddress, uint24_t bAddress); + //! @brief Get an offset corresponding to the current DMAMode and the index of the currently transferred byte. + int getModeOffset(int index); public: //! @brief DMA Control register (various information about the transfer) union {