diff --git a/ClockReceiver/JustInTime.hpp b/ClockReceiver/JustInTime.hpp index 6929bf3de..4f0321950 100644 --- a/ClockReceiver/JustInTime.hpp +++ b/ClockReceiver/JustInTime.hpp @@ -50,11 +50,13 @@ template () { flush(); + // TODO: I actually need to update time_until_event_ after the access occurring here has ended. + // So I guess I need to supply some sort of proxy object and jump on its destructor? return &object_; } /// Acts exactly as per the standard ->, but preserves constness. - forceinline const T *operator->() const { + forceinline const T *operator -> () const { auto non_const_this = const_cast *>(this); non_const_this->flush(); return &object_; @@ -78,6 +80,7 @@ template and when a previous point is passed. if constexpr (has_sequence_points::value) { time_until_event_ = object_.get_next_sequence_point(); assert(time_until_event_ > LocalTimeScale(0)); diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index e27842b63..d9a029b6a 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -685,6 +685,8 @@ class ConcreteMachine: while(ticks--) { clock_.update(); video_.last_valid()->notify_clock_tick(); // The video controller marshalls the one-second interrupt. + // TODO: I think I may have made a false assumption here; does + // the VGC have an independent 1-second interrupt? update_interrupts(); } diff --git a/Machines/Apple/AppleIIgs/Video.cpp b/Machines/Apple/AppleIIgs/Video.cpp index 9156ca39a..b72f86964 100644 --- a/Machines/Apple/AppleIIgs/Video.cpp +++ b/Machines/Apple/AppleIIgs/Video.cpp @@ -104,6 +104,21 @@ void VideoBase::advance(Cycles cycles) { } } +Cycles VideoBase::get_next_sequence_point() const { + const int cycles_into_row = cycles_into_frame_ % CyclesPerLine; + const int row = cycles_into_frame_ / CyclesPerLine; + + constexpr int sequence_point_offset = (5 + 8) * CyclesPerTick; + + // Handle every case that doesn't involve wrapping to the next row 0. + if(row <= 200) { + if(cycles_into_row < sequence_point_offset) return Cycles(sequence_point_offset - cycles_into_row); + if(row < 200) return Cycles(CyclesPerLine + sequence_point_offset - cycles_into_row); + } + + return Cycles(CyclesPerLine + sequence_point_offset - cycles_into_row + (Lines - row - 1)*CyclesPerLine); +} + void VideoBase::output_row(int row, int start, int end) { // Reasoned guesswork ahoy! // @@ -192,7 +207,8 @@ void VideoBase::output_row(int row, int start, int end) { palette_[c] = PaletteConvulve(entry); } - // TODO: obey line_control_ & 0x40 interrupt control bit. + // Post an interrupt if requested. + if(line_control_ & 0x40) set_interrupts(0x20); } if(next_pixel_) { diff --git a/Machines/Apple/AppleIIgs/Video.hpp b/Machines/Apple/AppleIIgs/Video.hpp index 17820426f..39d278b24 100644 --- a/Machines/Apple/AppleIIgs/Video.hpp +++ b/Machines/Apple/AppleIIgs/Video.hpp @@ -56,6 +56,9 @@ class VideoBase: public Apple::II::VideoSwitches { /// Gets the type of output. Outputs::Display::DisplayType get_display_type() const; + /// Determines the period until video might autonomously update its interrupt lines. + Cycles get_next_sequence_point() const; + private: Outputs::CRT::CRT crt_;