diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index c09deaa9f..e99a4dcaa 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -99,6 +99,12 @@ TMS9918::TMS9918(Personality p) { crt_->set_output_device(Outputs::CRT::OutputDevice::Monitor); crt_->set_visible_area(Outputs::CRT::Rect(0.055f, 0.025f, 0.9f, 0.9f)); crt_->set_input_gamma(2.8f); + + // The TMS remains in-phase with the NTSC colour clock; this is an empirical measurement + // intended to produce the correct relationship between the hard edges between pixels and + // the colour clock. It was eyeballed rather than derived from any knowledge of the TMS + // colour burst generator because I've yet to find any. + crt_->set_immediate_default_phase(0.85f); } Outputs::CRT::CRT *TMS9918::get_crt() { diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 2e1fb5c65..82f582f6b 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -379,6 +379,11 @@ void CRT::output_default_colour_burst(unsigned int number_of_cycles) { output_colour_burst(number_of_cycles, static_cast((phase_numerator_ * 256) / phase_denominator_ + (is_alernate_line_ ? 128 : 0))); } +void CRT::set_immediate_default_phase(float phase) { + phase = fmodf(phase, 1.0f); + phase_numerator_ = static_cast(phase * static_cast(phase_denominator_)); +} + void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider) { openGL_output_builder_.texture_builder.reduce_previous_allocation_to(number_of_cycles / source_divider); Scan scan; diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 521f1833b..90367a174 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -210,6 +210,13 @@ class CRT { */ void output_default_colour_burst(unsigned int number_of_cycles); + /*! Sets the current phase of the colour subcarrier used by output_default_colour_burst. + + @param phase The normalised instantaneous phase — 0.0f is the start of a colour cycle, 1.0f is the + end of a colour cycle, 0.25f is a quarter of the way through a colour cycle, etc. + */ + void set_immediate_default_phase(float phase); + /*! Attempts to allocate the given number of output samples for writing. The beginning of the most recently allocated area is used as the start