From 5ef1ba8d4fbfea0bd5ae1cd16437422f99b8ef2b Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 28 May 2020 01:17:45 +0200
Subject: [PATCH] Handling DMA's modes
---
sources/CPU/DMA/DMA.cpp | 35 +++++++++++++++++++++++++++--------
sources/CPU/DMA/DMA.hpp | 4 +++-
2 files changed, 30 insertions(+), 9 deletions(-)
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 {