diff --git a/ClockReceiver/ClockReceiver.hpp b/ClockReceiver/ClockReceiver.hpp index 6fe49cf1d..a621cbf1b 100644 --- a/ClockReceiver/ClockReceiver.hpp +++ b/ClockReceiver/ClockReceiver.hpp @@ -139,10 +139,10 @@ template class WrappedInt { Severs from @c this the effect of dividing by @c divisor; @c this will end up with the value of @c this modulo @c divisor and @c divided by @c divisor is returned. */ - forceinline T divide(const T &divisor) { - T result(length_ / divisor.length_); - length_ %= divisor.length_; - return result; + template forceinline Result divide(const T &divisor) { + Result r; + static_cast(this)->fill(r, divisor); + return r; } /*! @@ -177,6 +177,11 @@ class Cycles: public WrappedInt { result.length_ = length_; length_ = 0; } + + void fill(Cycles &result, const Cycles &divisor) { + result.length_ = length_ / divisor.length_; + length_ %= divisor.length_; + } }; /// Describes an integer number of half cycles: single clock signal transitions. @@ -215,6 +220,16 @@ class HalfCycles: public WrappedInt { result.length_ = length_; length_ = 0; } + + void fill(Cycles &result, const HalfCycles &divisor) { + result = Cycles(length_ / (divisor.length_ << 1)); + length_ %= (divisor.length_ << 1); + } + + void fill(HalfCycles &result, const HalfCycles &divisor) { + result.length_ = length_ / divisor.length_; + length_ %= divisor.length_; + } }; // Create a specialisation of WrappedInt::flush for converting HalfCycles to Cycles diff --git a/ClockReceiver/JustInTime.hpp b/ClockReceiver/JustInTime.hpp index 4f7bafe05..778ba93e2 100644 --- a/ClockReceiver/JustInTime.hpp +++ b/ClockReceiver/JustInTime.hpp @@ -21,7 +21,7 @@ Machines that accumulate HalfCycle time but supply to a Cycle-counted device may supply a separate @c TargetTimeScale at template declaration. */ -template class JustInTimeActor { +template class JustInTimeActor { public: /// Constructs a new JustInTimeActor using the same construction arguments as the included object. template JustInTimeActor(Args&&... args) : object_(std::forward(args)...) {} @@ -44,8 +44,14 @@ template ()); + void flush() { + if(!is_flushed_) { + if(divider == 1) { + object_.run_for(time_since_update_.template flush()); + } else { + object_.run_for(time_since_update_.template divide(LocalTimeScale(divider))); + } + } is_flushed_ = true; } diff --git a/Components/6850/6850.cpp b/Components/6850/6850.cpp index e935590ff..5b20be2cc 100644 --- a/Components/6850/6850.cpp +++ b/Components/6850/6850.cpp @@ -89,18 +89,20 @@ void ACIA::run_for(HalfCycles length) { const int transmit_advance = length.as_int(); const auto write_data_time_remaining = transmit.write_data_time_remaining(); - if(transmit_advance > write_data_time_remaining) { - if(next_transmission_ != NoTransmission) { - transmit.flush_writing(); - consider_transmission(); - transmit.advance_writer(transmit_advance - write_data_time_remaining); + if(write_data_time_remaining) { + if(transmit_advance > write_data_time_remaining) { + if(next_transmission_ != NoTransmission) { + transmit.flush_writing(); + consider_transmission(); + transmit.advance_writer(transmit_advance - write_data_time_remaining); + } else { + transmit.advance_writer(transmit_advance); + update_clocking_observer(); + interrupt_request_ |= transmit_interrupt_enabled_; + } } else { transmit.advance_writer(transmit_advance); - update_clocking_observer(); - interrupt_request_ |= transmit_interrupt_enabled_; } - } else { - transmit.advance_writer(transmit_advance); } // Reception. diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 09d91a47d..231b5f242 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -656,9 +656,11 @@ template class ConcreteMachin return mouse_; } + using IWMActor = JustInTimeActor; + class VIAPortHandler: public MOS::MOS6522::PortHandler { public: - VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, JustInTimeActor &iwm, Inputs::QuadratureMouse &mouse) : + VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, DeferredAudio &audio, IWMActor &iwm, Inputs::QuadratureMouse &mouse) : machine_(machine), clock_(clock), keyboard_(keyboard), audio_(audio), iwm_(iwm), mouse_(mouse) {} using Port = MOS::MOS6522::Port; @@ -764,14 +766,14 @@ template class ConcreteMachin RealTimeClock &clock_; Keyboard &keyboard_; DeferredAudio &audio_; - JustInTimeActor &iwm_; + IWMActor &iwm_; Inputs::QuadratureMouse &mouse_; }; CPU::MC68000::Processor mc68000_; DriveSpeedAccumulator drive_speed_accumulator_; - JustInTimeActor iwm_; + IWMActor iwm_; DeferredAudio audio_; Video video_; diff --git a/Machines/AtariST/AtariST.cpp b/Machines/AtariST/AtariST.cpp index 1a4d829a1..f161cfb8a 100644 --- a/Machines/AtariST/AtariST.cpp +++ b/Machines/AtariST/AtariST.cpp @@ -347,6 +347,8 @@ class ConcreteMachine: forceinline void advance_time(HalfCycles length) { cycles_since_audio_update_ += length; mfp_ += length; + keyboard_acia_ += length; + midi_acia_ += length; while(length >= cycles_until_video_event_) { length -= cycles_until_video_event_; @@ -366,12 +368,12 @@ class ConcreteMachine: } CPU::MC68000::Processor mc68000_; - JustInTimeActor video_; + JustInTimeActor