1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Adds the necessary routine for all machines to be able to respond to get_scan_status.

They all just as the CRT, as all are currently based on the CRT. Which doesn't currently know the total clock rate it would need to in order properly to scale the answer to the question. Further thought coming.
This commit is contained in:
Thomas Harte 2020-01-20 21:45:10 -05:00
parent e74f37d6ed
commit d97a073d1b
37 changed files with 151 additions and 1 deletions

View File

@ -60,6 +60,13 @@ void MultiCRTMachine::set_scan_target(Outputs::Display::ScanTarget *scan_target)
if(crt_machine) crt_machine->set_scan_target(scan_target);
}
Outputs::Display::ScanStatus MultiCRTMachine::get_scan_status() const {
CRTMachine::Machine *const crt_machine = machines_.front()->crt_machine();
if(crt_machine) crt_machine->get_scan_status();
return Outputs::Display::ScanStatus();
}
Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
return speaker_;
}

View File

@ -54,6 +54,7 @@ class MultiCRTMachine: public CRTMachine::Machine {
// Below is the standard CRTMachine::Machine interface; see there for documentation.
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override;
Outputs::Display::ScanStatus get_scan_status() const override;
Outputs::Speaker::Speaker *get_speaker() override;
void run_for(Time::Seconds duration) override;

View File

@ -43,6 +43,13 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
return &object_;
}
/// Acts exactly as per the standard ->, but preserves constness.
forceinline const T *operator->() const {
auto non_const_this = const_cast<JustInTimeActor<T, multiplier, divider, LocalTimeScale, TargetTimeScale> *>(this);
non_const_this->flush();
return &object_;
}
/// Returns a pointer to the included object without flushing time.
forceinline T *last_valid() {
return &object_;

View File

@ -84,6 +84,7 @@ template <class BusHandler> class MOS6560 {
}
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); }
Outputs::Speaker::Speaker *get_speaker() { return &speaker_; }

View File

@ -117,6 +117,10 @@ 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();
}
void TMS9918::set_display_type(Outputs::Display::DisplayType display_type) {
crt_.set_display_type(display_type);
}

View File

@ -44,6 +44,9 @@ class TMS9918: public Base {
/*! Sets the scan target this TMS will post content to. */
void set_scan_target(Outputs::Display::ScanTarget *);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
/*! Sets the type of display the CRT will request. */
void set_display_type(Outputs::Display::DisplayType);

View File

@ -335,6 +335,11 @@ class CRTCBusHandler {
crt_.set_scan_target(scan_target);
}
/// @returns The current scan status.
Outputs::Display::ScanStatus get_scan_status() const {
return crt_.get_scan_status();
}
/// Sets the type of display.
void set_display_type(Outputs::Display::DisplayType display_type) {
crt_.set_display_type(display_type);
@ -1006,6 +1011,11 @@ template <bool has_fdc> class ConcreteMachine:
crtc_bus_handler_.set_scan_target(scan_target);
}
/// A CRTMachine function; returns the current scan status.
Outputs::Display::ScanStatus get_scan_status() const final {
return crtc_bus_handler_.get_scan_status();
}
/// A CRTMachine function; sets the output display type.
void set_display_type(Outputs::Display::DisplayType display_type) override final {
crtc_bus_handler_.set_display_type(display_type);

View File

@ -421,6 +421,10 @@ 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();
}
/// Sets the type of display.
void set_display_type(Outputs::Display::DisplayType display_type) override {
video_.set_display_type(display_type);

View File

@ -47,6 +47,10 @@ 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();
}
void VideoBase::set_display_type(Outputs::Display::DisplayType display_type) {
crt_.set_display_type(display_type);
}

View File

@ -40,6 +40,9 @@ class VideoBase {
/// Sets the scan target.
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
/// Sets the type of output.
void set_display_type(Outputs::Display::DisplayType);

View File

@ -175,6 +175,10 @@ 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::Speaker::Speaker *get_speaker() override {
return &audio_.speaker;
}

View File

@ -37,6 +37,10 @@ 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();
}
void Video::run_for(HalfCycles duration) {
// Determine the current video and audio bases. These values don't appear to be latched, they apply immediately.
const size_t video_base = (use_alternate_screen_buffer_ ? (0xffff2700 >> 1) : (0xffffa700 >> 1)) & ram_mask_;

View File

@ -42,6 +42,9 @@ class Video {
*/
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
/*!
Produces the next @c duration period of pixels.
*/

View File

@ -161,6 +161,10 @@ class ConcreteMachine:
bus_->tia_.set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return bus_->tia_.get_scan_status();
}
Outputs::Speaker::Speaker *get_speaker() override {
return &bus_->speaker_;
}

View File

@ -142,6 +142,10 @@ 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();
}
void TIA::run_for(const Cycles cycles) {
int number_of_cycles = int(cycles.as_integral());

View File

@ -75,6 +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;
private:
Outputs::CRT::CRT crt_;

View File

@ -139,6 +139,10 @@ class ConcreteMachine:
video_->set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return video_->get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) final {
video_->set_display_type(display_type);
}

View File

@ -127,6 +127,10 @@ 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();
}
void Video::set_display_type(Outputs::Display::DisplayType display_type) {
crt_.set_display_type(display_type);
}

View File

@ -40,6 +40,9 @@ class Video {
*/
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
/*!
Sets the type of output.
*/

View File

@ -37,6 +37,11 @@ class Machine {
*/
virtual void set_scan_target(Outputs::Display::ScanTarget *scan_target) = 0;
/*!
@returns The current scan status.
*/
virtual Outputs::Display::ScanStatus get_scan_status() const = 0;
/// @returns The speaker that receives this machine's output, or @c nullptr if this machine is mute.
virtual Outputs::Speaker::Speaker *get_speaker() = 0;

View File

@ -185,6 +185,10 @@ class ConcreteMachine:
vdp_->set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return vdp_->get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) override {
vdp_->set_display_type(display_type);
}

View File

@ -626,6 +626,10 @@ class ConcreteMachine:
mos6560_.set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return mos6560_.get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) override final {
mos6560_.set_display_type(display_type);
}

View File

@ -383,6 +383,10 @@ class ConcreteMachine:
video_output_.set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return video_output_.get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) override {
video_output_.set_display_type(display_type);
}

View File

@ -56,6 +56,10 @@ 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();
}
void VideoOutput::set_display_type(Outputs::Display::DisplayType display_type) {
crt_.set_display_type(display_type);
}

View File

@ -39,6 +39,9 @@ class VideoOutput {
/// Sets the destination for output.
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
/// Sets the type of output.
void set_display_type(Outputs::Display::DisplayType);

View File

@ -282,6 +282,10 @@ class ConcreteMachine:
vdp_->set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return vdp_->get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) override {
vdp_->set_display_type(display_type);
}

View File

@ -177,6 +177,10 @@ class ConcreteMachine:
vdp_->set_scan_target(scan_target);
}
Outputs::Display::ScanStatus get_scan_status() const final {
return vdp_->get_scan_status();
}
void set_display_type(Outputs::Display::DisplayType display_type) override {
vdp_->set_display_type(display_type);
}

View File

@ -556,6 +556,10 @@ 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();
}
void set_display_type(Outputs::Display::DisplayType display_type) final {
video_output_.set_display_type(display_type);
}

View File

@ -56,6 +56,10 @@ 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();
}
void VideoOutput::set_colour_rom(const std::vector<uint8_t> &rom) {
for(std::size_t c = 0; c < 8; c++) {
colour_forms_[c] = 0;

View File

@ -27,6 +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;
private:
uint8_t *ram_;

View File

@ -109,3 +109,7 @@ void Video::output_byte(uint8_t byte) {
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();
}

View File

@ -36,12 +36,16 @@ class Video {
/// Sets the current sync output.
void set_sync(bool sync);
/// Causes @c byte to be serialised into pixels and output over the next four cycles.
void output_byte(uint8_t byte);
/// Sets the scan target.
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
/// Gets the current scan status.
Outputs::Display::ScanStatus get_scan_status() const;
private:
bool sync_ = false;
uint8_t *line_data_ = nullptr;

View File

@ -318,6 +318,10 @@ 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::Speaker::Speaker *get_speaker() override final {
return is_zx81 ? &speaker_ : nullptr;
}

View File

@ -67,7 +67,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"

View File

@ -418,6 +418,8 @@ void CRT::output_data(int number_of_cycles, size_t number_of_samples) {
output_scan(&scan);
}
// MARK: - Getters.
Outputs::Display::Rect CRT::get_rect_for_area(int first_line_after_sync, int number_of_lines, int first_cycle_after_sync, int number_of_cycles, float aspect_ratio) {
first_cycle_after_sync *= time_multiplier_;
number_of_cycles *= time_multiplier_;
@ -465,3 +467,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 {
return Outputs::Display::ScanStatus();
}

View File

@ -274,6 +274,9 @@ 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;
/*! Sets the display type that will be nominated to the scan target. */
void set_display_type(Outputs::Display::DisplayType);

View File

@ -11,6 +11,7 @@
#include <cstddef>
#include <cstdint>
#include "../ClockReceiver/TimeTypes.hpp"
namespace Outputs {
namespace Display {
@ -309,6 +310,18 @@ struct ScanTarget {
virtual void announce(Event event, bool is_visible, const Scan::EndPoint &location, uint8_t composite_amplitude) {}
};
struct ScanStatus {
/// The current (prediced) length of a field.
Time::Seconds field_duration;
/// The difference applied to the field_duration estimate during the last field.
Time::Seconds field_duration_gradient;
/// The distance into the current field, from 0 (start of field) to 1 (end of field).
/// This is unlikely to be linear but should increase monotonically, being a measure
/// 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;
};
/*!
Provides a null target for scans.
*/