diff --git a/Machines/Amiga/Audio.cpp b/Machines/Amiga/Audio.cpp index a7ebebd83..94b963da6 100644 --- a/Machines/Amiga/Audio.cpp +++ b/Machines/Amiga/Audio.cpp @@ -111,7 +111,7 @@ bool Audio::advance_dma(int channel) { } void Audio::output() { - constexpr InterruptFlag interrupts[] = { + constexpr InterruptFlag::FlagT interrupts[] = { InterruptFlag::AudioChannel0, InterruptFlag::AudioChannel1, InterruptFlag::AudioChannel2, diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 782a8e8cc..b2d94740b 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -21,35 +21,6 @@ using namespace Amiga; -// TODO: I don't think the nonsense below, which was intended to allow a typed enum but also -// clean combination, really works. Rethink. -namespace { - -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 {}; - -constexpr uint16_t AudioFlags[] = { - DMAMask::value, - DMAMask::value, - DMAMask::value, - DMAMask::value, -}; -constexpr auto BlitterFlag = DMAMask::value; -constexpr auto BitplaneFlag = DMAMask::value; -constexpr auto CopperFlag = DMAMask::value; -constexpr auto DiskFlag = DMAMask::value; -constexpr auto SpritesFlag = DMAMask::value; - -} - #define DMA_CONSTRUCT *this, reinterpret_cast(map.chip_ram.data()), map.chip_ram.size() >> 1 Chipset::Chipset(MemoryMap &map, int input_clock_rate) : @@ -94,17 +65,17 @@ void Chipset::set_cia_interrupts(bool cia_a_interrupt, bool cia_b_interrupt) { // If latched, is it only on a leading edge? // interrupt_requests_ &= ~InterruptMask::value; interrupt_requests_ |= - (cia_a_interrupt ? InterruptMask::value : 0) | - (cia_b_interrupt ? InterruptMask::value : 0); + (cia_a_interrupt ? InterruptFlag::IOPortsAndTimers : 0) | + (cia_b_interrupt ? InterruptFlag::External : 0); update_interrupts(); } -void Chipset::posit_interrupt(InterruptFlag flag) { - interrupt_requests_ |= uint16_t(flag); +void Chipset::posit_interrupt(InterruptFlag::FlagT flag) { + interrupt_requests_ |= flag; update_interrupts(); } -void DMADeviceBase::posit_interrupt(InterruptFlag flag) { +void DMADeviceBase::posit_interrupt(InterruptFlag::FlagT flag) { chipset_.posit_interrupt(flag); } @@ -557,9 +528,10 @@ template bool Chipset::perform_cycle() { } } + constexpr auto BitplaneEnabled = DMAFlag::AllBelow | DMAFlag::Bitplane; if( horizontal_fetch_ != HorizontalFetch::Stopped && - (dma_control_ & BitplaneFlag) == BitplaneFlag && + (dma_control_ & BitplaneEnabled) == BitplaneEnabled && fetch_vertical_ && bitplanes_.advance_dma(cycle - horizontal_offset_) ) { @@ -622,7 +594,8 @@ template bool Chipset::perform_cycle() { } if constexpr (cycle >= 0x08 && cycle < 0x0e) { - if((dma_control_ & DiskFlag) == DiskFlag) { + constexpr auto DiskEnabled = DMAFlag::AllBelow | DMAFlag::Disk; + if((dma_control_ & DiskEnabled) == DiskEnabled) { if(disk_.advance_dma()) { return false; } @@ -634,6 +607,13 @@ template bool Chipset::perform_cycle() { static_assert(channel >= 0 && channel < 4); static_assert(cycle != 0x15 || channel == 3); + constexpr DMAFlag::FlagT AudioFlags[] = { + DMAFlag::AllBelow | DMAFlag::AudioChannel0, + DMAFlag::AllBelow | DMAFlag::AudioChannel1, + DMAFlag::AllBelow | DMAFlag::AudioChannel2, + DMAFlag::AllBelow | DMAFlag::AudioChannel3, + }; + if((dma_control_ & AudioFlags[channel]) == AudioFlags[channel]) { if(audio_.advance_dma(channel)) { return false; @@ -642,7 +622,8 @@ template bool Chipset::perform_cycle() { } if constexpr (cycle >= 0x16 && cycle < 0x36) { - if(y_ >= vertical_blank_height_ && (dma_control_ & SpritesFlag) == SpritesFlag) { + constexpr auto SpritesEnabled = DMAFlag::AllBelow | DMAFlag::Sprites; + if(y_ >= vertical_blank_height_ && (dma_control_ & SpritesEnabled) == SpritesEnabled) { constexpr auto sprite_id = (cycle - 0x16) >> 2; static_assert(sprite_id >= 0 && sprite_id < std::tuple_size::value); @@ -656,7 +637,8 @@ template bool Chipset::perform_cycle() { // is just possibly to pass to the Copper. // // The Blitter and CPU are dealt with outside of the odd/even test. - if((dma_control_ & CopperFlag) == CopperFlag) { + constexpr auto CopperEnabled = DMAFlag::AllBelow | DMAFlag::Copper; + if((dma_control_ & CopperEnabled) == CopperEnabled) { if(copper_.advance_dma(uint16_t(((y_ & 0xff) << 8) | cycle), blitter_.get_status())) { return false; } @@ -667,7 +649,10 @@ template bool Chipset::perform_cycle() { // Down here: give first refusal to the Blitter, otherwise // pass on to the CPU. - return (dma_control_ & BlitterFlag) != BlitterFlag || !blitter_.advance_dma(); + // + // TODO: Blitter nasty flag. Who owns that? + constexpr auto BlitterEnabled = DMAFlag::AllBelow | DMAFlag::Blitter; + return (dma_control_ & BlitterEnabled) != BlitterEnabled || !blitter_.advance_dma(); } /// Performs all slots starting with @c first_slot and ending just before @c last_slot. @@ -764,7 +749,7 @@ template Chipset::Changes Chipset::run(HalfCycles length) { if(y_ == short_field_height_ + is_long_field_) { ++vsyncs; - interrupt_requests_ |= InterruptMask::value; + interrupt_requests_ |= InterruptFlag::VerticalBlank; update_interrupts(); y_ = 0; @@ -832,17 +817,17 @@ void Chipset::update_interrupts() { const uint16_t enabled_requests = interrupt_enable_ & interrupt_requests_ & 0x3fff; if(enabled_requests && (interrupt_enable_ & 0x4000)) { - if(enabled_requests & InterruptMask::value) { + if(enabled_requests & InterruptFlag::External) { interrupt_level_ = 6; - } else if(enabled_requests & InterruptMask::value) { + } else if(enabled_requests & (InterruptFlag::SerialPortReceive | InterruptFlag::DiskSyncMatch)) { interrupt_level_ = 5; - } else if(enabled_requests & InterruptMask::value) { + } else if(enabled_requests & (InterruptFlag::AudioChannel0 | InterruptFlag::AudioChannel1 | InterruptFlag::AudioChannel2 | InterruptFlag::AudioChannel3)) { interrupt_level_ = 4; - } else if(enabled_requests & InterruptMask::value) { + } else if(enabled_requests & (InterruptFlag::Copper | InterruptFlag::VerticalBlank | InterruptFlag::Blitter)) { interrupt_level_ = 3; - } else if(enabled_requests & InterruptMask::value) { + } else if(enabled_requests & InterruptFlag::IOPortsAndTimers) { interrupt_level_ = 2; - } else if(enabled_requests & InterruptMask::value) { + } else if(enabled_requests & (InterruptFlag::SerialPortTransmit | InterruptFlag::DiskBlock | InterruptFlag::Software)) { interrupt_level_ = 1; } } diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index f74a2b4a7..1e95e7209 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -125,7 +125,7 @@ class Chipset: private ClockingHint::Observer { int interrupt_level_ = 0; void update_interrupts(); - void posit_interrupt(InterruptFlag); + void posit_interrupt(InterruptFlag::FlagT); // MARK: - Scheduler. diff --git a/Machines/Amiga/DMADevice.hpp b/Machines/Amiga/DMADevice.hpp index 99d0c7377..c3d1d7e0b 100644 --- a/Machines/Amiga/DMADevice.hpp +++ b/Machines/Amiga/DMADevice.hpp @@ -24,7 +24,7 @@ class DMADeviceBase { DMADeviceBase(Chipset &chipset, uint16_t *ram, size_t word_size) : chipset_(chipset), ram_(ram), ram_mask_(uint32_t(word_size - 1)) {} - void posit_interrupt(Amiga::InterruptFlag); + void posit_interrupt(Amiga::InterruptFlag::FlagT); protected: Chipset &chipset_; diff --git a/Machines/Amiga/Flags.hpp b/Machines/Amiga/Flags.hpp index 7fed0a7e1..029c1a1d8 100644 --- a/Machines/Amiga/Flags.hpp +++ b/Machines/Amiga/Flags.hpp @@ -11,39 +11,43 @@ 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. -}; +namespace InterruptFlag { + using FlagT = uint16_t; -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, -}; + constexpr FlagT SerialPortTransmit = 1 << 0; + constexpr FlagT DiskBlock = 1 << 1; + constexpr FlagT Software = 1 << 2; + constexpr FlagT IOPortsAndTimers = 1 << 3; // i.e. CIA A. + constexpr FlagT Copper = 1 << 4; + constexpr FlagT VerticalBlank = 1 << 5; + constexpr FlagT Blitter = 1 << 6; + constexpr FlagT AudioChannel0 = 1 << 7; + constexpr FlagT AudioChannel1 = 1 << 8; + constexpr FlagT AudioChannel2 = 1 << 9; + constexpr FlagT AudioChannel3 = 1 << 10; + constexpr FlagT SerialPortReceive = 1 << 11; + constexpr FlagT DiskSyncMatch = 1 << 12; + constexpr FlagT External = 1 << 13; // i.e. CIA B. +} -}; +namespace DMAFlag { + using FlagT = uint16_t; + + constexpr FlagT AudioChannel0 = 1 << 0; + constexpr FlagT AudioChannel1 = 1 << 1; + constexpr FlagT AudioChannel2 = 1 << 2; + constexpr FlagT AudioChannel3 = 1 << 3; + constexpr FlagT Disk = 1 << 4; + constexpr FlagT Sprites = 1 << 5; + constexpr FlagT Blitter = 1 << 6; + constexpr FlagT Copper = 1 << 7; + constexpr FlagT Bitplane = 1 << 8; + constexpr FlagT AllBelow = 1 << 9; + constexpr FlagT BlitterPriority = 1 << 10; + constexpr FlagT BlitterZero = 1 << 13; + constexpr FlagT BlitterBusy = 1 << 14; +} + +} #endif /* Flags_hpp */