From b34403164ecb151c5eda7fbae42410c9c8462ef6 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 18 Aug 2023 14:30:40 -0400 Subject: [PATCH] Abstract out VGC interrupt register; fix clearing bug. --- Machines/Apple/AppleIIgs/Video.cpp | 18 ++++------- Machines/Apple/AppleIIgs/Video.hpp | 52 ++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/Machines/Apple/AppleIIgs/Video.cpp b/Machines/Apple/AppleIIgs/Video.cpp index e78e6ff4b..3f6269193 100644 --- a/Machines/Apple/AppleIIgs/Video.cpp +++ b/Machines/Apple/AppleIIgs/Video.cpp @@ -285,7 +285,7 @@ void Video::output_row(int row, int start, int end) { // Post an interrupt if requested. if(line_control_ & 0x40) { - set_interrupts(0x20); + interrupts_.add(0x20); } // Set up appropriately for fill mode (or not). @@ -498,19 +498,19 @@ uint8_t Video::get_new_video() { } void Video::clear_interrupts(uint8_t mask) { - set_interrupts(interrupts_ & ~(mask & 0x60)); + interrupts_.clear(mask); } void Video::set_interrupt_register(uint8_t mask) { - set_interrupts(interrupts_ | (mask & 0x6)); + interrupts_.set_control(mask); } uint8_t Video::get_interrupt_register() { - return interrupts_; + return interrupts_.status(); } bool Video::get_interrupt_line() { - return (interrupts_&0x80) || (megaii_interrupt_mask_&megaii_interrupt_state_); + return interrupts_.active() || (megaii_interrupt_mask_ & megaii_interrupt_state_); } void Video::set_megaii_interrupts_enabled(uint8_t mask) { @@ -526,13 +526,7 @@ void Video::clear_megaii_interrupts() { } void Video::notify_clock_tick() { - set_interrupts(interrupts_ | 0x40); -} - -void Video::set_interrupts(uint8_t new_value) { - interrupts_ = new_value & 0x7f; - if((interrupts_ >> 4) & interrupts_ & 0x6) - interrupts_ |= 0x80; + interrupts_.add(0x40); } void Video::set_border_colour(uint8_t colour) { diff --git a/Machines/Apple/AppleIIgs/Video.hpp b/Machines/Apple/AppleIIgs/Video.hpp index a6f5c9788..9d30f2dff 100644 --- a/Machines/Apple/AppleIIgs/Video.hpp +++ b/Machines/Apple/AppleIIgs/Video.hpp @@ -123,8 +123,56 @@ class Video: public Apple::II::VideoSwitches { void advance(Cycles); uint8_t new_video_ = 0x01; - uint8_t interrupts_ = 0x00; - void set_interrupts(uint8_t); + + class Interrupts { + public: + void add(uint8_t value) { + // Taken literally, status accumulates regardless of being enabled, + // potentially to be polled, it simply doesn't trigger an interrupt. + value_ |= value; + test(); + } + + void clear(uint8_t value) { + // Zeroes in bits 5 or 6 clear the respective interrupts. + value_ &= value | ~0x60; + test(); + } + + void set_control(uint8_t value) { + // Ones in bits 1 or 2 enable the respective interrupts. + value_ = (value_ & ~0x6) | (value & 0x6); + test(); + } + + uint8_t status() const { + return value_; + } + + bool active() const { + return value_ & 0x80; + } + + private: + void test() { + value_ &= 0x7f; + if((value_ >> 4) & value_ & 0x6) { + value_ |= 0x80; + } + } + + // Overall meaning of value is as per the VGC interrupt register, i.e. + // + // b7: interrupt status; + // b6: 1-second interrupt status; + // b5: scan-line interrupt status; + // b4: reserved; + // b3: reserved; + // b2: 1-second interrupt enable; + // b1: scan-line interrupt enable; + // b0: reserved. + uint8_t value_ = 0x00; + } interrupts_; int cycles_into_frame_ = 0; const uint8_t *ram_ = nullptr;