diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index c6015fe7d..4a40cf5ee 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -278,7 +278,7 @@ template class MOS6560 { switch(output_state_) { case State::Sync: crt_.output_sync(cycles_in_state_ * 4); break; case State::ColourBurst: crt_.output_colour_burst(cycles_in_state_ * 4, (is_odd_frame_ || is_odd_line_) ? 128 : 0); break; - case State::Border: output_border(cycles_in_state_ * 4); break; + case State::Border: crt_.output_level(cycles_in_state_ * 4, registers_.borderColour); break; case State::Pixels: crt_.output_data(cycles_in_state_ * 4); break; } output_state_ = this_state_; @@ -400,7 +400,7 @@ template class MOS6560 { case 0xf: { uint16_t new_border_colour = colours_[value & 0x07]; if(this_state_ == State::Border && new_border_colour != registers_.borderColour) { - output_border(cycles_in_state_ * 4); + crt_.output_level(cycles_in_state_ * 4, registers_.borderColour); cycles_in_state_ = 0; } registers_.invertedCells = !((value >> 3)&1); @@ -503,11 +503,6 @@ template class MOS6560 { uint16_t colours_[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; uint16_t *pixel_pointer = nullptr; - void output_border(int number_of_cycles) { - uint16_t *colour_pointer = reinterpret_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = registers_.borderColour; - crt_.output_level(number_of_cycles); - } struct { int cycles_per_line = 0; diff --git a/Components/9918/Implementation/9918.cpp b/Components/9918/Implementation/9918.cpp index 177e86dda..eb32d691e 100644 --- a/Components/9918/Implementation/9918.cpp +++ b/Components/9918/Implementation/9918.cpp @@ -688,11 +688,7 @@ void Base::output_border(int cycles, [[maybe_unused]] uint32_t cram // If the border colour is 0, that can be communicated // more efficiently as an explicit blank. if(border_colour) { - uint32_t *const pixel_target = reinterpret_cast(crt_.begin_data(1)); - if(pixel_target) { - *pixel_target = border_colour; - } - crt_.output_level(cycles); + crt_.output_level(cycles, border_colour); } else { crt_.output_blank(cycles); } diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 7c2848fee..bb2d6d24b 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -389,9 +389,7 @@ class CRTCBusHandler { // A black border can be output via crt_.output_blank for a minor performance // win; otherwise paint whatever the border colour really is. if(border_) { - uint8_t *const colour_pointer = static_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = border_; - crt_.output_level(length * 16); + crt_.output_level(length * 16, border_); } else { crt_.output_blank(length * 16); } diff --git a/Machines/Atari/ST/Video.cpp b/Machines/Atari/ST/Video.cpp index 1aba47372..6fb41f39c 100644 --- a/Machines/Atari/ST/Video.cpp +++ b/Machines/Atari/ST/Video.cpp @@ -633,10 +633,7 @@ void Video::VideoStream::will_change_border_colour() { void Video::VideoStream::flush_border() { // Output colour 0 for the entirety of duration_ (or black, if this is 1bpp mode). - uint16_t *const colour_pointer = reinterpret_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = (bpp_ != OutputBpp::One) ? palette_[0] : 0; - crt_.output_level(duration_*2); - + crt_.output_level(duration_ * 2, (bpp_ != OutputBpp::One) ? palette_[0] : 0); duration_ = 0; } diff --git a/Machines/Enterprise/Nick.cpp b/Machines/Enterprise/Nick.cpp index 6da43d8cb..914292fdc 100644 --- a/Machines/Enterprise/Nick.cpp +++ b/Machines/Enterprise/Nick.cpp @@ -442,22 +442,19 @@ void Nick::set_output_type(OutputType type, bool force_flush) { return; } if(output_duration_) { - switch(output_type_) { - case OutputType::Border: { - uint16_t *const colour_pointer = reinterpret_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = border_colour_; - crt_.output_level(output_duration_*16); - } break; + const int duration = output_duration_ * 16; + switch(output_type_) { case OutputType::Pixels: { - crt_.output_data(output_duration_*16, size_t(output_duration_*column_size_)); + crt_.output_data(duration, size_t(output_duration_*column_size_)); pixel_pointer_ = nullptr; allocated_pointer_ = nullptr; } break; - case OutputType::Sync: crt_.output_sync(output_duration_*16); break; - case OutputType::Blank: crt_.output_blank(output_duration_*16); break; - case OutputType::ColourBurst: crt_.output_colour_burst(output_duration_*16, 0); break; + case OutputType::Border: crt_.output_level(duration, border_colour_); break; + case OutputType::Sync: crt_.output_sync(duration); break; + case OutputType::Blank: crt_.output_blank(duration); break; + case OutputType::ColourBurst: crt_.output_colour_burst(duration, 0); break; } } diff --git a/Machines/Sinclair/ZX8081/Video.cpp b/Machines/Sinclair/ZX8081/Video.cpp index da1e72109..0f6fad3c3 100644 --- a/Machines/Sinclair/ZX8081/Video.cpp +++ b/Machines/Sinclair/ZX8081/Video.cpp @@ -59,9 +59,7 @@ void Video::flush(bool next_sync) { } // Any pending pixels being dealt with, pad with the white level. - uint8_t *colour_pointer = static_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = 0xff; - crt_.output_level(int(time_since_update_.as_integral())); + crt_.output_level(time_since_update_.as(), 0xff); } time_since_update_ = 0; diff --git a/Machines/Sinclair/ZXSpectrum/Video.hpp b/Machines/Sinclair/ZXSpectrum/Video.hpp index 7f0f8ac51..f62e67376 100644 --- a/Machines/Sinclair/ZXSpectrum/Video.hpp +++ b/Machines/Sinclair/ZXSpectrum/Video.hpp @@ -133,7 +133,7 @@ template class Video { // Output plain border line. if(offset < sync_position) { const int border_duration = std::min(sync_position, end_offset) - offset; - output_border(border_duration); + crt_.output_level(border_duration, border_colour_); offset += border_duration; } } else { @@ -199,7 +199,7 @@ template class Video { if(offset >= 256 && offset < sync_position && end_offset > offset) { const int border_duration = std::min(sync_position, end_offset) - offset; - output_border(border_duration); + crt_.output_level(border_duration, border_colour_); offset += border_duration; } } @@ -231,8 +231,7 @@ template class Video { } if(offset >= burst_position+burst_length && end_offset > offset) { - const int border_duration = end_offset - offset; - output_border(border_duration); + crt_.output_level(end_offset - offset, border_colour_); } } @@ -242,12 +241,6 @@ template class Video { } private: - void output_border(int duration) { - uint8_t *const colour_pointer = crt_.begin_data(1); - if(colour_pointer) *colour_pointer = border_colour_; - crt_.output_level(duration); - } - static constexpr int half_cycles_per_line() { if constexpr (timing == Timing::FortyEightK) { // TODO: determine real figure here, if one exists. diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index 87abbda7f..fc9bbe794 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -180,6 +180,18 @@ class CRT { */ void output_level(int number_of_cycles); + /*! Outputs @c value for @c number_of_cycles . + + @param value The value to output. + @param number_of_cycles The number of cycles to repeat the output for. + */ + template + void output_level(int number_of_cycles, IntT value) { + auto colour_pointer = reinterpret_cast(begin_data(1)); + if(colour_pointer) *colour_pointer = value; + output_level(number_of_cycles); + } + /*! Declares that the caller has created a run of data via @c begin_data that is at least @c number_of_samples long, and that the first @c number_of_samples should be spread over @c number_of_cycles.