diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index df8502f71..733fccd75 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -68,7 +68,7 @@ class IRQDelegatePortHandler: public PortHandler { /// Sets the delegate that will receive notification of changes in the interrupt line. void set_interrupt_delegate(Delegate *delegate); - /// Overrides PortHandler::set_interrupt_status, notifying the delegate if one is set. + /// Overrides @c PortHandler::set_interrupt_status, notifying the delegate if one is set. void set_interrupt_status(bool new_status); private: diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index a1d9aecdc..f2bc2e0ac 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -256,6 +256,20 @@ template pick_card_messaging_group(card); } + void card_did_change_interrupt_flags(Apple::II::Card *) final { + bool nmi = false; + bool irq = false; + + for(const auto &card: cards_) { + if(card) { + nmi |= card->nmi(); + irq |= card->irq(); + } + } + m6502_.set_nmi_line(nmi); + m6502_.set_irq_line(irq); + } + Apple::II::Mockingboard *mockingboard() { return dynamic_cast(cards_[MockingboardSlot - 1].get()); } diff --git a/Machines/Apple/AppleII/Card.hpp b/Machines/Apple/AppleII/Card.hpp index a5b6f0afa..54d43cd0c 100644 --- a/Machines/Apple/AppleII/Card.hpp +++ b/Machines/Apple/AppleII/Card.hpp @@ -54,7 +54,7 @@ class Card { This is posted only to cards that announced a select constraint. Cards with no constraints, that want to be informed of every machine cycle, will receive - a call to perform_bus_operation every cycle and should use that for time keeping. + a call to @c perform_bus_operation every cycle and should use that for time keeping. */ virtual void run_for([[maybe_unused]] Cycles cycles, [[maybe_unused]] int stretches) {} @@ -93,8 +93,15 @@ class Card { /*! Cards may supply a target for activity observation if desired. */ virtual void set_activity_observer([[maybe_unused]] Activity::Observer *observer) {} + /// @returns The current semantic NMI line output of this card. + virtual bool nmi() { return false; } + + /// @returns The current semantic IRQ line output of this card. + virtual bool irq() { return false; } + struct Delegate { virtual void card_did_change_select_constraints(Card *card) = 0; + virtual void card_did_change_interrupt_flags(Card *card) = 0; }; void set_delegate(Delegate *delegate) { delegate_ = delegate; diff --git a/Machines/Apple/AppleII/Mockingboard.hpp b/Machines/Apple/AppleII/Mockingboard.hpp index dbde129e5..b56ebecc5 100644 --- a/Machines/Apple/AppleII/Mockingboard.hpp +++ b/Machines/Apple/AppleII/Mockingboard.hpp @@ -18,7 +18,10 @@ namespace Apple::II { class Mockingboard: public Card { public: Mockingboard() : - vias_{ {handlers_[0]}, {handlers_[1]} } {} + vias_{ {handlers_[0]}, {handlers_[1]} } { + set_select_constraints(0); + handlers_[0].card = handlers_[1].card = this; + } void perform_bus_operation(Select select, bool is_read, uint16_t address, uint8_t *value) final { if(!(select & Device)) { @@ -33,8 +36,32 @@ class Mockingboard: public Card { } } + void run_for(Cycles cycles, int) final { + vias_[0].run_for(cycles); + vias_[1].run_for(cycles); + } + + bool nmi() final { + return handlers_[1].interrupt; + } + + bool irq() final { + return handlers_[0].interrupt; + } + + void did_change_interrupt_flags() { + delegate_->card_did_change_interrupt_flags(this); + } + private: - class AYVIA: public MOS::MOS6522::IRQDelegatePortHandler { + struct AYVIA: public MOS::MOS6522::PortHandler { + void set_interrupt_status(bool status) { + interrupt = status; + card->did_change_interrupt_flags(); + } + + bool interrupt; + Mockingboard *card = nullptr; }; MOS::MOS6522::MOS6522 vias_[2];