From dda154c7c68b0e9fae5caa4e9a62ee1d5f8806dd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 9 Aug 2021 20:31:14 -0400 Subject: [PATCH] Adds nonsense disk reads, which seems to lead to bitplane and blitter requests. Progress, at last! --- Machines/Amiga/Chipset.cpp | 79 +++++++++++++++++++++++++------------- Machines/Amiga/Chipset.hpp | 37 ++++++++++++++++++ 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 42dc3d941..0edc6c56a 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -18,23 +18,17 @@ using namespace Amiga; namespace { -enum InterruptFlag: uint16_t { - SerialPortTransmit = 1 << 0, - DiskBlock = 1 << 1, - Software = 1 << 2, - IOPortsAndTimers = 1 << 3, // i.e. CIA A. - Copper = 1 << 4, - VerticalBlank = 1 << 5, - Blitter = 1 << 6, - AudioChannel0 = 1 << 7, - AudioChannel1 = 1 << 8, - AudioChannel2 = 1 << 9, - AudioChannel3 = 1 << 10, - SerialPortReceive = 1 << 11, - DiskSyncMatch = 1 << 12, - External = 1 << 13, // i.e. CIA B. +template struct Mask { + static constexpr uint16_t value = 0; }; +template struct Mask { + static constexpr uint16_t value = uint16_t(F) | Mask::value; +}; + +template struct InterruptMask: Mask {}; +template struct DMAMask: Mask {}; + } Chipset::Chipset(uint16_t *ram, size_t size) : @@ -54,10 +48,15 @@ Chipset::Changes Chipset::run_until_cpu_slot() { void Chipset::set_cia_interrupts(bool cia_a, bool cia_b) { // TODO: are these really latched, or are they active live? - interrupt_requests_ &= ~(InterruptFlag::IOPortsAndTimers | InterruptFlag::External); + interrupt_requests_ &= ~InterruptMask::value; interrupt_requests_ |= - (cia_a ? InterruptFlag::IOPortsAndTimers : 0) | - (cia_b ? InterruptFlag::External : 0); + (cia_a ? InterruptMask::value : 0) | + (cia_b ? InterruptMask::value : 0); + update_interrupts(); +} + +void Chipset::posit_interrupt(InterruptFlag flag) { + interrupt_requests_ |= uint16_t(flag); update_interrupts(); } @@ -220,6 +219,9 @@ template void Chipset::output() { } template bool Chipset::perform_cycle() { + constexpr auto CopperFlag = DMAMask::value; + constexpr auto DiskFlag = DMAMask::value; + if constexpr (cycle & 1) { // Odd slot priority is: // @@ -227,7 +229,7 @@ template bool Chipset::perform_cycle() { // 2. Bitplane. // 3. Blitter. // 4. CPU. - if((dma_control_ & 0x280) == 0x280) { + if((dma_control_ & CopperFlag) == CopperFlag) { if(copper_.advance(uint16_t(((y_ & 0xff) << 8) | (cycle & 0xfe)))) { return false; } @@ -242,6 +244,11 @@ template bool Chipset::perform_cycle() { // 2. Disk, then audio, then sprites depending on region. // 3. Blitter. // 4. CPU. + if constexpr (cycle >= 4 && cycle <= 6) { + if((dma_control_ & DiskFlag) == DiskFlag) { + disk_.advance(); + } + } } return true; @@ -325,7 +332,7 @@ template Chipset::Changes Chipset::run(HalfCycles length) { if(y_ == frame_height_) { ++changes.vsyncs; - interrupt_requests_ |= InterruptFlag::VerticalBlank; + interrupt_requests_ |= InterruptMask::value; update_interrupts(); y_ = 0; @@ -346,17 +353,17 @@ void Chipset::update_interrupts() { const uint16_t enabled_requests = interrupt_enable_ & interrupt_requests_ & 0x3fff; if(enabled_requests && (interrupt_enable_ & 0x4000)) { - if(enabled_requests & (InterruptFlag::External)) { + if(enabled_requests & InterruptMask::value) { interrupt_level_ = 6; - } else if(enabled_requests & (InterruptFlag::SerialPortReceive | InterruptFlag::DiskSyncMatch)) { + } else if(enabled_requests & InterruptMask::value) { interrupt_level_ = 5; - } else if(enabled_requests & (InterruptFlag::AudioChannel0 | InterruptFlag::AudioChannel1 | InterruptFlag::AudioChannel2 | InterruptFlag::AudioChannel3)) { + } else if(enabled_requests & InterruptMask::value) { interrupt_level_ = 4; - } else if(enabled_requests & (InterruptFlag::Copper | InterruptFlag::VerticalBlank | InterruptFlag::Blitter)) { + } else if(enabled_requests & InterruptMask::value) { interrupt_level_ = 3; - } else if(enabled_requests & (InterruptFlag::IOPortsAndTimers)) { + } else if(enabled_requests & InterruptMask::value) { interrupt_level_ = 2; - } else if(enabled_requests & (InterruptFlag::SerialPortTransmit | InterruptFlag::DiskBlock | InterruptFlag::Software)) { + } else if(enabled_requests & InterruptMask::value) { interrupt_level_ = 1; } } @@ -671,6 +678,25 @@ void Chipset::Sprite::set_image_data(int slot, uint16_t value) { LOG("Sprite image data " << slot << " to " << PADHEX(4) << value); } +// MARK: - Disk. + +void Chipset::DiskDMA::advance() { + if(!dma_enable_) return; + + if(!write_) { + // TODO: run an actual PLL, collect actual disk data. + if(length_) { + ram_[address_ & ram_mask_] = 0xffff; + ++address_; + --length_; + + if(!length_) { + chipset_.posit_interrupt(InterruptFlag::DiskBlock); + } + } + } +} + // MARK: - CRT connection. void Chipset::set_scan_target(Outputs::Display::ScanTarget *scan_target) { @@ -688,3 +714,4 @@ void Chipset::set_display_type(Outputs::Display::DisplayType type) { Outputs::Display::DisplayType Chipset::get_display_type() const { return crt_.get_display_type(); } + diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 39d33deaa..598a8a55c 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -19,6 +19,39 @@ namespace Amiga { +enum class InterruptFlag: uint16_t { + SerialPortTransmit = 1 << 0, + DiskBlock = 1 << 1, + Software = 1 << 2, + IOPortsAndTimers = 1 << 3, // i.e. CIA A. + Copper = 1 << 4, + VerticalBlank = 1 << 5, + Blitter = 1 << 6, + AudioChannel0 = 1 << 7, + AudioChannel1 = 1 << 8, + AudioChannel2 = 1 << 9, + AudioChannel3 = 1 << 10, + SerialPortReceive = 1 << 11, + DiskSyncMatch = 1 << 12, + External = 1 << 13, // i.e. CIA B. +}; + +enum class DMAFlag: uint16_t { + AudioChannel0 = 1 << 0, + AudioChannel1 = 1 << 1, + AudioChannel2 = 1 << 2, + AudioChannel3 = 1 << 3, + Disk = 1 << 4, + Sprites = 1 << 5, + Blitter = 1 << 6, + Copper = 1 << 7, + Bitplane = 1 << 8, + AllBelow = 1 << 9, + BlitterPriority = 1 << 10, + BlitterZero = 1 << 13, + BlitterBusy = 1 << 14, +}; + class Chipset { public: Chipset(uint16_t *ram, size_t size); @@ -72,6 +105,7 @@ class Chipset { uint16_t *ram_ = nullptr; uint32_t ram_mask_ = 0; }; + friend DMADevice; // MARK: - Interrupts. @@ -80,6 +114,7 @@ class Chipset { int interrupt_level_ = 0; void update_interrupts(); + void posit_interrupt(InterruptFlag); // MARK: - Scheduler. @@ -190,6 +225,8 @@ class Chipset { } } + void advance(); + private: uint32_t address_; uint16_t length_;