diff --git a/Components/6526/6526.hpp b/Components/6526/6526.hpp index 6026de66d..656fd344a 100644 --- a/Components/6526/6526.hpp +++ b/Components/6526/6526.hpp @@ -57,6 +57,9 @@ template class MOS6526: /// Pulses the TOD input the specified number of times. void advance_tod(int count); + /// @returns @c true if the interrupt output is active, @c false otherwise. + bool get_interrupt_line(); + private: PortHandlerT &port_handler_; diff --git a/Components/6526/Implementation/6526Implementation.hpp b/Components/6526/Implementation/6526Implementation.hpp index 11b2e0a04..abcab7d8d 100644 --- a/Components/6526/Implementation/6526Implementation.hpp +++ b/Components/6526/Implementation/6526Implementation.hpp @@ -37,12 +37,14 @@ template void MOS6526::update_interrupts() { if(interrupt_state_ & interrupt_control_) { interrupt_state_ |= 0x80; - - printf("6526 should signal interrupt\n"); - assert(false); } } +template +bool MOS6526::get_interrupt_line() { + return interrupt_state_ & 0x80; +} + template void MOS6526::write(int address, uint8_t value) { address &= 0xf; diff --git a/Machines/Amiga/Amiga.cpp b/Machines/Amiga/Amiga.cpp index caf65cdd7..f4b607550 100644 --- a/Machines/Amiga/Amiga.cpp +++ b/Machines/Amiga/Amiga.cpp @@ -82,7 +82,9 @@ class ConcreteMachine: const auto changes = chipset_.run_for(cycle.length); cia_a_.advance_tod(changes.vsyncs); cia_b_.advance_tod(changes.hsyncs); - mc68000_.set_interrupt_level(changes.interrupt_level); + + chipset_.set_cia_interrupts(cia_a_.get_interrupt_line(), cia_b_.get_interrupt_line()); + mc68000_.set_interrupt_level(chipset_.get_interrupt_level()); // Check for assertion of reset. if(cycle.operation & Microcycle::Reset) { diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 5e05f808c..097158166 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -22,7 +22,7 @@ enum InterruptFlag: uint16_t { SerialPortTransmit = 1 << 0, DiskBlock = 1 << 1, Software = 1 << 2, - IOPortsAndTimers = 1 << 3, + IOPortsAndTimers = 1 << 3, // i.e. CIA A. Copper = 1 << 4, VerticalBlank = 1 << 5, Blitter = 1 << 6, @@ -32,7 +32,7 @@ enum InterruptFlag: uint16_t { AudioChannel3 = 1 << 10, SerialPortReceive = 1 << 11, DiskSyncMatch = 1 << 12, - External = 1 << 13, + External = 1 << 13, // i.e. CIA B. }; } @@ -51,6 +51,17 @@ Chipset::Changes Chipset::run_until_cpu_slot() { return run(); } +void Chipset::set_cia_interrupts(bool cia_a, bool cia_b) { + // TODO: are these really latched, or are they active live? + if(cia_a || cia_b) { + interrupt_requests_ |= + (cia_a ? InterruptFlag::IOPortsAndTimers : 0) | + (cia_b ? InterruptFlag::External : 0); + update_interrupts(); + } +} + + bool Chipset::Copper::advance(uint16_t position) { switch(state_) { default: return false; diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 5cf1af12a..171baba4b 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -43,6 +43,9 @@ class Chipset { /// Performs the provided microcycle, which the caller guarantees to be a memory access. void perform(const CPU::MC68000::Microcycle &); + /// Sets the current state of the CIA interrupt lines. + void set_cia_interrupts(bool cia_a, bool cia_b); + /// Provides the chipset's current interrupt level. int get_interrupt_level() { return interrupt_level_;