1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-24 12:30:17 +00:00

Merge pull request #1254 from TomHarte/BordersAplenty

Unify repeated setup/execution of output_level.
This commit is contained in:
Thomas Harte 2023-12-07 11:45:42 -05:00 committed by GitHub
commit d94791a82d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 29 additions and 48 deletions

View File

@ -278,7 +278,7 @@ template <class BusHandler> class MOS6560 {
switch(output_state_) { switch(output_state_) {
case State::Sync: crt_.output_sync(cycles_in_state_ * 4); break; 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::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<uint16_t>(cycles_in_state_ * 4, registers_.borderColour); break;
case State::Pixels: crt_.output_data(cycles_in_state_ * 4); break; case State::Pixels: crt_.output_data(cycles_in_state_ * 4); break;
} }
output_state_ = this_state_; output_state_ = this_state_;
@ -400,7 +400,7 @@ template <class BusHandler> class MOS6560 {
case 0xf: { case 0xf: {
uint16_t new_border_colour = colours_[value & 0x07]; uint16_t new_border_colour = colours_[value & 0x07];
if(this_state_ == State::Border && new_border_colour != registers_.borderColour) { if(this_state_ == State::Border && new_border_colour != registers_.borderColour) {
output_border(cycles_in_state_ * 4); crt_.output_level<uint16_t>(cycles_in_state_ * 4, registers_.borderColour);
cycles_in_state_ = 0; cycles_in_state_ = 0;
} }
registers_.invertedCells = !((value >> 3)&1); registers_.invertedCells = !((value >> 3)&1);
@ -503,11 +503,6 @@ template <class BusHandler> class MOS6560 {
uint16_t colours_[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 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; uint16_t *pixel_pointer = nullptr;
void output_border(int number_of_cycles) {
uint16_t *colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
if(colour_pointer) *colour_pointer = registers_.borderColour;
crt_.output_level(number_of_cycles);
}
struct { struct {
int cycles_per_line = 0; int cycles_per_line = 0;

View File

@ -667,14 +667,9 @@ void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram
border_colour = Storage<personality>::colour_ram_[16 + background_colour_]; border_colour = Storage<personality>::colour_ram_[16 + background_colour_];
if(cram_dot) { if(cram_dot) {
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_.begin_data(1));
if(pixel_target) {
*pixel_target = border_colour | cram_dot;
}
// Four CRT cycles is one pixel width, so this doesn't need clock conversion. // Four CRT cycles is one pixel width, so this doesn't need clock conversion.
// TODO: on the Mega Drive it may be only 3 colour cycles, depending on mode. // TODO: on the Mega Drive it may be only 3 colour cycles, depending on mode.
crt_.output_level(4); crt_.output_level<uint32_t>(4, border_colour | cram_dot);
cycles -= 4; cycles -= 4;
} }
} else { } else {
@ -688,11 +683,7 @@ void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram
// If the border colour is 0, that can be communicated // If the border colour is 0, that can be communicated
// more efficiently as an explicit blank. // more efficiently as an explicit blank.
if(border_colour) { if(border_colour) {
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_.begin_data(1)); crt_.output_level<uint32_t>(cycles, border_colour);
if(pixel_target) {
*pixel_target = border_colour;
}
crt_.output_level(cycles);
} else { } else {
crt_.output_blank(cycles); crt_.output_blank(cycles);
} }

View File

@ -389,9 +389,7 @@ class CRTCBusHandler {
// A black border can be output via crt_.output_blank for a minor performance // A black border can be output via crt_.output_blank for a minor performance
// win; otherwise paint whatever the border colour really is. // win; otherwise paint whatever the border colour really is.
if(border_) { if(border_) {
uint8_t *const colour_pointer = static_cast<uint8_t *>(crt_.begin_data(1)); crt_.output_level<uint8_t>(length * 16, border_);
if(colour_pointer) *colour_pointer = border_;
crt_.output_level(length * 16);
} else { } else {
crt_.output_blank(length * 16); crt_.output_blank(length * 16);
} }

View File

@ -633,10 +633,7 @@ void Video::VideoStream::will_change_border_colour() {
void Video::VideoStream::flush_border() { void Video::VideoStream::flush_border() {
// Output colour 0 for the entirety of duration_ (or black, if this is 1bpp mode). // Output colour 0 for the entirety of duration_ (or black, if this is 1bpp mode).
uint16_t *const colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1)); crt_.output_level<uint16_t>(duration_ * 2, (bpp_ != OutputBpp::One) ? palette_[0] : 0);
if(colour_pointer) *colour_pointer = (bpp_ != OutputBpp::One) ? palette_[0] : 0;
crt_.output_level(duration_*2);
duration_ = 0; duration_ = 0;
} }

View File

@ -442,22 +442,19 @@ void Nick::set_output_type(OutputType type, bool force_flush) {
return; return;
} }
if(output_duration_) { if(output_duration_) {
switch(output_type_) { const int duration = output_duration_ * 16;
case OutputType::Border: {
uint16_t *const colour_pointer = reinterpret_cast<uint16_t *>(crt_.begin_data(1));
if(colour_pointer) *colour_pointer = border_colour_;
crt_.output_level(output_duration_*16);
} break;
switch(output_type_) {
case OutputType::Pixels: { 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; pixel_pointer_ = nullptr;
allocated_pointer_ = nullptr; allocated_pointer_ = nullptr;
} break; } break;
case OutputType::Sync: crt_.output_sync(output_duration_*16); break; case OutputType::Border: crt_.output_level<uint16_t>(duration, border_colour_); break;
case OutputType::Blank: crt_.output_blank(output_duration_*16); break; case OutputType::Sync: crt_.output_sync(duration); break;
case OutputType::ColourBurst: crt_.output_colour_burst(output_duration_*16, 0); break; case OutputType::Blank: crt_.output_blank(duration); break;
case OutputType::ColourBurst: crt_.output_colour_burst(duration, 0); break;
} }
} }

View File

@ -59,9 +59,7 @@ void Video::flush(bool next_sync) {
} }
// Any pending pixels being dealt with, pad with the white level. // Any pending pixels being dealt with, pad with the white level.
uint8_t *colour_pointer = static_cast<uint8_t *>(crt_.begin_data(1)); crt_.output_level<uint8_t>(time_since_update_.as<int>(), 0xff);
if(colour_pointer) *colour_pointer = 0xff;
crt_.output_level(int(time_since_update_.as_integral()));
} }
time_since_update_ = 0; time_since_update_ = 0;

View File

@ -133,7 +133,7 @@ template <Timing timing> class Video {
// Output plain border line. // Output plain border line.
if(offset < sync_position) { if(offset < sync_position) {
const int border_duration = std::min(sync_position, end_offset) - offset; const int border_duration = std::min(sync_position, end_offset) - offset;
output_border(border_duration); crt_.output_level<uint8_t>(border_duration, border_colour_);
offset += border_duration; offset += border_duration;
} }
} else { } else {
@ -199,7 +199,7 @@ template <Timing timing> class Video {
if(offset >= 256 && offset < sync_position && end_offset > offset) { if(offset >= 256 && offset < sync_position && end_offset > offset) {
const int border_duration = std::min(sync_position, end_offset) - offset; const int border_duration = std::min(sync_position, end_offset) - offset;
output_border(border_duration); crt_.output_level<uint8_t>(border_duration, border_colour_);
offset += border_duration; offset += border_duration;
} }
} }
@ -231,8 +231,7 @@ template <Timing timing> class Video {
} }
if(offset >= burst_position+burst_length && end_offset > offset) { if(offset >= burst_position+burst_length && end_offset > offset) {
const int border_duration = end_offset - offset; crt_.output_level<uint8_t>(end_offset - offset, border_colour_);
output_border(border_duration);
} }
} }
@ -242,12 +241,6 @@ template <Timing timing> class Video {
} }
private: 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() { static constexpr int half_cycles_per_line() {
if constexpr (timing == Timing::FortyEightK) { if constexpr (timing == Timing::FortyEightK) {
// TODO: determine real figure here, if one exists. // TODO: determine real figure here, if one exists.

View File

@ -180,6 +180,18 @@ class CRT {
*/ */
void output_level(int number_of_cycles); 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 <typename IntT>
void output_level(int number_of_cycles, IntT value) {
auto colour_pointer = reinterpret_cast<IntT *>(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 /*! 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. long, and that the first @c number_of_samples should be spread over @c number_of_cycles.