1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Ensures a proper size handoff and implements a ripple feature I happened to find a forum post about.

This commit is contained in:
Thomas Harte 2019-12-19 22:58:07 -05:00
parent 0007dc23b3
commit 3d83f5ab49
2 changed files with 25 additions and 12 deletions

View File

@ -507,7 +507,7 @@ class ConcreteMachine:
// that's implemented, just offers magical zero-cost DMA insertion and
// extrication.
if(dma_->get_bus_request_line()) {
dma_->bus_grant(reinterpret_cast<uint16_t *>(ram_.data()), ram_.size());
dma_->bus_grant(reinterpret_cast<uint16_t *>(ram_.data()), ram_.size() >> 1);
}
}
void set_gpip_input() {

View File

@ -102,10 +102,18 @@ void DMAController::write(int address, uint16_t value) {
control_ = value;
break;
// DMA addressing.
// DMA addressing; cf. http://www.atari-forum.com/viewtopic.php?t=30289 on a hardware
// feature emulated here: 'carry' will ripple upwards if a write resets the top bit
// of the byte it is adjusting.
case 4: address_ = int((address_ & 0x00ffff) | ((value & 0xff) << 16)); break;
case 5: address_ = int((address_ & 0xff00ff) | ((value & 0xff) << 8)); break;
case 6: address_ = int((address_ & 0xffff00) | ((value & 0xfe) << 0)); break; // Lowest bit: discarded.
case 5:
if((value << 8) ^ address_ & ~(value << 8) & 0x8000) address_ += 0x10000;
address_ = int((address_ & 0xff00ff) | ((value & 0xff) << 8));
break;
case 6:
if(value ^ address_ & ~value & 0x80) address_ += 0x100;
address_ = int((address_ & 0xffff00) | ((value & 0xfe) << 0));
break; // Lowest bit: discarded.
}
}
@ -171,6 +179,7 @@ int DMAController::bus_grant(uint16_t *ram, size_t size) {
bus_request_line_ = false;
if(delegate_) delegate_->dma_controller_did_change_output(this);
size <<= 1; // Convert to bytes.
if(control_ & Control::Direction) {
// TODO: writes.
return 0;
@ -179,10 +188,12 @@ int DMAController::bus_grant(uint16_t *ram, size_t size) {
if(!buffer_[active_buffer_ ^ 1].is_full) return 0;
for(int c = 0; c < 8; ++c) {
ram[size_t(address_ >> 1) & (size - 1)] = uint16_t(
(buffer_[active_buffer_ ^ 1].contents[(c << 1) + 0] << 8) |
(buffer_[active_buffer_ ^ 1].contents[(c << 1) + 1] << 0)
);
if(size_t(address_) < size) {
ram[address_ >> 1] = uint16_t(
(buffer_[active_buffer_ ^ 1].contents[(c << 1) + 0] << 8) |
(buffer_[active_buffer_ ^ 1].contents[(c << 1) + 1] << 0)
);
}
address_ += 2;
}
buffer_[active_buffer_ ^ 1].is_full = false;
@ -191,10 +202,12 @@ int DMAController::bus_grant(uint16_t *ram, size_t size) {
if(!buffer_[active_buffer_ ].is_full) return 8;
for(int c = 0; c < 8; ++c) {
ram[size_t(address_ >> 1) & (size - 1)] = uint16_t(
(buffer_[active_buffer_].contents[(c << 1) + 0] << 8) |
(buffer_[active_buffer_].contents[(c << 1) + 1] << 0)
);
if(size_t(address_) < size) {
ram[address_ >> 1] = uint16_t(
(buffer_[active_buffer_].contents[(c << 1) + 0] << 8) |
(buffer_[active_buffer_].contents[(c << 1) + 1] << 0)
);
}
address_ += 2;
}
buffer_[active_buffer_].is_full = false;