diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index fc8da5682..e975ef596 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -83,9 +83,9 @@ template class MOS6560 { speaker_.set_input_rate(static_cast(clock_rate / 4.0)); } - void set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const { return crt_.get_scan_status(); } - void set_display_type(Outputs::Display::DisplayType display_type) { crt_.set_display_type(display_type); } + void set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } + Outputs::Display::ScanStatus get_scaled_scan_status() const { return crt_.get_scaled_scan_status() / 4.0f; } + void set_display_type(Outputs::Display::DisplayType display_type) { crt_.set_display_type(display_type); } Outputs::Speaker::Speaker *get_speaker() { return &speaker_; } void set_high_frequency_cutoff(float cutoff) { diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index de1d34015..93eb05180 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -117,8 +117,8 @@ void TMS9918::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus TMS9918::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus TMS9918::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status(); } void TMS9918::set_display_type(Outputs::Display::DisplayType display_type) { diff --git a/Components/9918/9918.hpp b/Components/9918/9918.hpp index 15908b6bf..2cca01693 100644 --- a/Components/9918/9918.hpp +++ b/Components/9918/9918.hpp @@ -45,7 +45,7 @@ class TMS9918: public Base { void set_scan_target(Outputs::Display::ScanTarget *); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; /*! Sets the type of display the CRT will request. */ void set_display_type(Outputs::Display::DisplayType); diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 83aa396c5..19c68e772 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -336,8 +336,8 @@ class CRTCBusHandler { } /// @returns The current scan status. - Outputs::Display::ScanStatus get_scan_status() const { - return crt_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 64.0f; } /// Sets the type of display. @@ -1012,8 +1012,8 @@ template class ConcreteMachine: } /// A CRTMachine function; returns the current scan status. - Outputs::Display::ScanStatus get_scan_status() const final { - return crtc_bus_handler_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return crtc_bus_handler_.get_scaled_scan_status(); } /// A CRTMachine function; sets the output display type. diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 6c2ae0641..036b71b37 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -421,8 +421,8 @@ template class ConcreteMachine: video_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_.get_scaled_scan_status(); } /// Sets the type of display. diff --git a/Machines/Apple/AppleII/Video.cpp b/Machines/Apple/AppleII/Video.cpp index 996ba5cf6..373987834 100644 --- a/Machines/Apple/AppleII/Video.cpp +++ b/Machines/Apple/AppleII/Video.cpp @@ -47,8 +47,8 @@ void VideoBase::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus VideoBase::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus VideoBase::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 14.0f; } void VideoBase::set_display_type(Outputs::Display::DisplayType display_type) { diff --git a/Machines/Apple/AppleII/Video.hpp b/Machines/Apple/AppleII/Video.hpp index 3c1c6bb20..ac7085a07 100644 --- a/Machines/Apple/AppleII/Video.hpp +++ b/Machines/Apple/AppleII/Video.hpp @@ -41,7 +41,7 @@ class VideoBase { void set_scan_target(Outputs::Display::ScanTarget *scan_target); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; /// Sets the type of output. void set_display_type(Outputs::Display::DisplayType); diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index c6bce2d79..75e57e65e 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -175,8 +175,8 @@ template class ConcreteMachin video_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_.get_scaled_scan_status(); } Outputs::Speaker::Speaker *get_speaker() override { diff --git a/Machines/Apple/Macintosh/Video.cpp b/Machines/Apple/Macintosh/Video.cpp index a04c62a4d..00276a419 100644 --- a/Machines/Apple/Macintosh/Video.cpp +++ b/Machines/Apple/Macintosh/Video.cpp @@ -37,8 +37,8 @@ void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus Video::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus Video::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 2.0f; } void Video::run_for(HalfCycles duration) { diff --git a/Machines/Apple/Macintosh/Video.hpp b/Machines/Apple/Macintosh/Video.hpp index 59f5282a2..88dd9d1e1 100644 --- a/Machines/Apple/Macintosh/Video.hpp +++ b/Machines/Apple/Macintosh/Video.hpp @@ -43,7 +43,7 @@ class Video { void set_scan_target(Outputs::Display::ScanTarget *scan_target); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; /*! Produces the next @c duration period of pixels. diff --git a/Machines/Atari/2600/Atari2600.cpp b/Machines/Atari/2600/Atari2600.cpp index 9ce05d7a8..9b4a357ae 100644 --- a/Machines/Atari/2600/Atari2600.cpp +++ b/Machines/Atari/2600/Atari2600.cpp @@ -161,8 +161,8 @@ class ConcreteMachine: bus_->tia_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return bus_->tia_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return bus_->tia_.get_scaled_scan_status() / 3.0f; } Outputs::Speaker::Speaker *get_speaker() override { diff --git a/Machines/Atari/2600/TIA.cpp b/Machines/Atari/2600/TIA.cpp index 4b17bdbf9..5bc5bae9e 100644 --- a/Machines/Atari/2600/TIA.cpp +++ b/Machines/Atari/2600/TIA.cpp @@ -142,8 +142,8 @@ void TIA::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus TIA::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus TIA::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 2.0f; } void TIA::run_for(const Cycles cycles) { diff --git a/Machines/Atari/2600/TIA.hpp b/Machines/Atari/2600/TIA.hpp index 45b238145..0ecf1cb4a 100644 --- a/Machines/Atari/2600/TIA.hpp +++ b/Machines/Atari/2600/TIA.hpp @@ -75,7 +75,7 @@ class TIA { void set_crt_delegate(Outputs::CRT::Delegate *); void set_scan_target(Outputs::Display::ScanTarget *); - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; private: Outputs::CRT::CRT crt_; diff --git a/Machines/Atari/ST/AtariST.cpp b/Machines/Atari/ST/AtariST.cpp index c6f91004b..6a45e6854 100644 --- a/Machines/Atari/ST/AtariST.cpp +++ b/Machines/Atari/ST/AtariST.cpp @@ -139,8 +139,8 @@ class ConcreteMachine: video_->set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_->get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_->get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) final { diff --git a/Machines/Atari/ST/Video.cpp b/Machines/Atari/ST/Video.cpp index 6937ae72a..1170928f1 100644 --- a/Machines/Atari/ST/Video.cpp +++ b/Machines/Atari/ST/Video.cpp @@ -127,8 +127,8 @@ void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus Video::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus Video::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 2.0f; } void Video::set_display_type(Outputs::Display::DisplayType display_type) { diff --git a/Machines/Atari/ST/Video.hpp b/Machines/Atari/ST/Video.hpp index a971b800d..46196ceed 100644 --- a/Machines/Atari/ST/Video.hpp +++ b/Machines/Atari/ST/Video.hpp @@ -41,7 +41,7 @@ class Video { void set_scan_target(Outputs::Display::ScanTarget *scan_target); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; /*! Sets the type of output. diff --git a/Machines/CRTMachine.hpp b/Machines/CRTMachine.hpp index 09577098c..e6432551a 100644 --- a/Machines/CRTMachine.hpp +++ b/Machines/CRTMachine.hpp @@ -40,7 +40,9 @@ class Machine { /*! @returns The current scan status. */ - virtual Outputs::Display::ScanStatus get_scan_status() const = 0; + virtual Outputs::Display::ScanStatus get_scan_status() const { + return get_scaled_scan_status() / float(clock_rate_); + } /// @returns The speaker that receives this machine's output, or @c nullptr if this machine is mute. virtual Outputs::Speaker::Speaker *get_speaker() = 0; @@ -115,6 +117,15 @@ class Machine { return clock_rate_; } + virtual Outputs::Display::ScanStatus get_scaled_scan_status() const { + // This deliberately sets up an infinite loop if the user hasn't + // overridden at least one of this or get_scan_status. + // + // Most likely you want to override this, and let the base class + // throw in a divide-by-clock-rate at the end for you. + return get_scan_status(); + } + /*! Maps from Configurable::Display to Outputs::Display::VideoSignal and calls @c set_display_type with the result. diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp index 65c26fbca..631dc74f3 100644 --- a/Machines/ColecoVision/ColecoVision.cpp +++ b/Machines/ColecoVision/ColecoVision.cpp @@ -185,8 +185,8 @@ class ConcreteMachine: vdp_->set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return vdp_->get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return vdp_->get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) override { diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 0b2fe74bd..1a6c1eec3 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -626,8 +626,8 @@ class ConcreteMachine: mos6560_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return mos6560_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return mos6560_.get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) override final { diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 868cf26f0..c01a11fa9 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -383,8 +383,8 @@ class ConcreteMachine: video_output_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_output_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_output_.get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) override { diff --git a/Machines/Electron/Video.cpp b/Machines/Electron/Video.cpp index d87fbb721..88de46806 100644 --- a/Machines/Electron/Video.cpp +++ b/Machines/Electron/Video.cpp @@ -56,8 +56,8 @@ void VideoOutput::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus VideoOutput::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus VideoOutput::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / float(crt_cycles_multiplier); } void VideoOutput::set_display_type(Outputs::Display::DisplayType display_type) { diff --git a/Machines/Electron/Video.hpp b/Machines/Electron/Video.hpp index 06ab4f797..af8e57111 100644 --- a/Machines/Electron/Video.hpp +++ b/Machines/Electron/Video.hpp @@ -40,7 +40,7 @@ class VideoOutput { void set_scan_target(Outputs::Display::ScanTarget *scan_target); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; /// Sets the type of output. void set_display_type(Outputs::Display::DisplayType); diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 76ee2fff3..9cc894620 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -282,8 +282,8 @@ class ConcreteMachine: vdp_->set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return vdp_->get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return vdp_->get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) override { diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp index e6116f989..11a9a13c0 100644 --- a/Machines/MasterSystem/MasterSystem.cpp +++ b/Machines/MasterSystem/MasterSystem.cpp @@ -177,8 +177,8 @@ class ConcreteMachine: vdp_->set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return vdp_->get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return vdp_->get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) override { diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 742cf36fc..bfad07a82 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -556,8 +556,8 @@ template class Co video_output_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_output_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_output_.get_scaled_scan_status(); } void set_display_type(Outputs::Display::DisplayType display_type) final { diff --git a/Machines/Oric/Video.cpp b/Machines/Oric/Video.cpp index d0414a591..79e9dffc9 100644 --- a/Machines/Oric/Video.cpp +++ b/Machines/Oric/Video.cpp @@ -56,8 +56,8 @@ void VideoOutput::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus VideoOutput::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus VideoOutput::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 6.0f; } void VideoOutput::set_colour_rom(const std::vector &rom) { diff --git a/Machines/Oric/Video.hpp b/Machines/Oric/Video.hpp index 00b75051f..68e767ca1 100644 --- a/Machines/Oric/Video.hpp +++ b/Machines/Oric/Video.hpp @@ -27,7 +27,7 @@ class VideoOutput { void set_scan_target(Outputs::Display::ScanTarget *scan_target); void set_display_type(Outputs::Display::DisplayType display_type); - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; private: uint8_t *ram_; diff --git a/Machines/ZX8081/Video.cpp b/Machines/ZX8081/Video.cpp index 89b46f020..10507a864 100644 --- a/Machines/ZX8081/Video.cpp +++ b/Machines/ZX8081/Video.cpp @@ -110,6 +110,6 @@ void Video::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus Video::get_scan_status() const { - return crt_.get_scan_status(); +Outputs::Display::ScanStatus Video::get_scaled_scan_status() const { + return crt_.get_scaled_scan_status() / 0.5f; } diff --git a/Machines/ZX8081/Video.hpp b/Machines/ZX8081/Video.hpp index 5f6719e31..b99e18f33 100644 --- a/Machines/ZX8081/Video.hpp +++ b/Machines/ZX8081/Video.hpp @@ -44,7 +44,7 @@ class Video { void set_scan_target(Outputs::Display::ScanTarget *scan_target); /// Gets the current scan status. - Outputs::Display::ScanStatus get_scan_status() const; + Outputs::Display::ScanStatus get_scaled_scan_status() const; private: bool sync_ = false; diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 87ec3e1a9..51a563c9c 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -318,8 +318,8 @@ template class ConcreteMachine: video_.set_scan_target(scan_target); } - Outputs::Display::ScanStatus get_scan_status() const final { - return video_.get_scan_status(); + Outputs::Display::ScanStatus get_scaled_scan_status() const final { + return video_.get_scaled_scan_status(); } Outputs::Speaker::Speaker *get_speaker() override final { diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index f0872443c..f909108ca 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -468,7 +468,7 @@ Outputs::Display::Rect CRT::get_rect_for_area(int first_line_after_sync, int num return Outputs::Display::Rect(start_x, start_y, width, height); } -Outputs::Display::ScanStatus CRT::get_scan_status() const { +Outputs::Display::ScanStatus CRT::get_scaled_scan_status() const { Outputs::Display::ScanStatus status; status.field_duration = float(vertical_flywheel_->get_locked_period()) / float(time_multiplier_); status.field_duration_gradient = float(vertical_flywheel_->get_last_period_adjustment()) / float(time_multiplier_); diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index c44aab1f9..7117d4ade 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -274,8 +274,11 @@ class CRT { /*! Sets the scan target for CRT output. */ void set_scan_target(Outputs::Display::ScanTarget *); - /*! Gets current scan status. */ - Outputs::Display::ScanStatus get_scan_status() const; + /*! + Gets current scan status, with time based fields being in the input scale — e.g. if you're supplying + 86 cycles/line and 98 lines/field then it'll return a field duration of 86*98. + */ + Outputs::Display::ScanStatus get_scaled_scan_status() const; /*! Sets the display type that will be nominated to the scan target. */ void set_display_type(Outputs::Display::DisplayType); diff --git a/Outputs/ScanTarget.hpp b/Outputs/ScanTarget.hpp index 0fd94c9b9..1a131a5ba 100644 --- a/Outputs/ScanTarget.hpp +++ b/Outputs/ScanTarget.hpp @@ -320,6 +320,30 @@ struct ScanStatus { /// of the current vertical position — i.e. if current_position = 0.8 then a caller can /// conclude that the top 80% of the visible part of the display has been painted. float current_position; + + /*! + @returns this ScanStatus, with time-relative fields scaled by dividing them by @c dividend. + */ + ScanStatus operator / (float dividend) { + const ScanStatus result = { + .field_duration = field_duration / dividend, + .field_duration_gradient = field_duration_gradient / dividend, + .current_position = current_position + }; + return result; + } + + /*! + @returns this ScanStatus, with time-relative fields scaled by multiplying them by @c multiplier. + */ + ScanStatus operator * (float multiplier) { + const ScanStatus result = { + .field_duration = field_duration * multiplier, + .field_duration_gradient = field_duration_gradient * multiplier, + .current_position = current_position + }; + return result; + } }; /*!