mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 15:31:09 +00:00
Ensures proper manipulation of scan_statuses, leading to the correct result out of a CRTMachine.
Possibly with the exception of the TMS, as I appear to have uncovered an unrelated issue there.
This commit is contained in:
parent
e7fff6e123
commit
a71c5946f0
@ -83,9 +83,9 @@ template <class BusHandler> class MOS6560 {
|
||||
speaker_.set_input_rate(static_cast<float>(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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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 <bool has_fdc> 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.
|
||||
|
@ -421,8 +421,8 @@ template <Analyser::Static::AppleII::Target::Model model> 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.
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -175,8 +175,8 @@ template <Analyser::Static::Macintosh::Target::Model model> 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 {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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_;
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -556,8 +556,8 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> 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 {
|
||||
|
@ -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<uint8_t> &rom) {
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -318,8 +318,8 @@ template<bool is_zx81> 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 {
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
Loading…
x
Reference in New Issue
Block a user