mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Merge pull request #1254 from TomHarte/BordersAplenty
Unify repeated setup/execution of output_level.
This commit is contained in:
commit
d94791a82d
@ -278,7 +278,7 @@ template <class BusHandler> 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<uint16_t>(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 BusHandler> 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<uint16_t>(cycles_in_state_ * 4, registers_.borderColour);
|
||||
cycles_in_state_ = 0;
|
||||
}
|
||||
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 *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 {
|
||||
int cycles_per_line = 0;
|
||||
|
@ -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_];
|
||||
|
||||
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.
|
||||
// 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;
|
||||
}
|
||||
} 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
|
||||
// more efficiently as an explicit blank.
|
||||
if(border_colour) {
|
||||
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_.begin_data(1));
|
||||
if(pixel_target) {
|
||||
*pixel_target = border_colour;
|
||||
}
|
||||
crt_.output_level(cycles);
|
||||
crt_.output_level<uint32_t>(cycles, border_colour);
|
||||
} else {
|
||||
crt_.output_blank(cycles);
|
||||
}
|
||||
|
@ -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<uint8_t *>(crt_.begin_data(1));
|
||||
if(colour_pointer) *colour_pointer = border_;
|
||||
crt_.output_level(length * 16);
|
||||
crt_.output_level<uint8_t>(length * 16, border_);
|
||||
} else {
|
||||
crt_.output_blank(length * 16);
|
||||
}
|
||||
|
@ -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<uint16_t *>(crt_.begin_data(1));
|
||||
if(colour_pointer) *colour_pointer = (bpp_ != OutputBpp::One) ? palette_[0] : 0;
|
||||
crt_.output_level(duration_*2);
|
||||
|
||||
crt_.output_level<uint16_t>(duration_ * 2, (bpp_ != OutputBpp::One) ? palette_[0] : 0);
|
||||
duration_ = 0;
|
||||
}
|
||||
|
||||
|
@ -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<uint16_t *>(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<uint16_t>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<uint8_t *>(crt_.begin_data(1));
|
||||
if(colour_pointer) *colour_pointer = 0xff;
|
||||
crt_.output_level(int(time_since_update_.as_integral()));
|
||||
crt_.output_level<uint8_t>(time_since_update_.as<int>(), 0xff);
|
||||
}
|
||||
|
||||
time_since_update_ = 0;
|
||||
|
@ -133,7 +133,7 @@ template <Timing timing> 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<uint8_t>(border_duration, border_colour_);
|
||||
offset += border_duration;
|
||||
}
|
||||
} else {
|
||||
@ -199,7 +199,7 @@ template <Timing timing> 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<uint8_t>(border_duration, border_colour_);
|
||||
offset += border_duration;
|
||||
}
|
||||
}
|
||||
@ -231,8 +231,7 @@ template <Timing timing> 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<uint8_t>(end_offset - offset, border_colour_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,12 +241,6 @@ template <Timing timing> 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.
|
||||
|
@ -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 <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
|
||||
long, and that the first @c number_of_samples should be spread over @c number_of_cycles.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user