Merge pull request #1833 from TomHarte/6847Borders
Add 6847 border colours.
This commit is contained in:
3 files changed
+117
-25
No files matched your search
+62
-25
@@ -140,23 +140,40 @@ MC6847Base::MC6847Base(const Outputs::Display::Type display_type) :
|
||||
crt_.set_display_type(Outputs::Display::DisplayType::CompositeColour);
|
||||
}
|
||||
|
||||
void MC6847Base::pixel_line(const int line_begin, const int line_end) {
|
||||
if(line_begin < LineLayout::EndOfLeftBorder && line_end >= LineLayout::EndOfLeftBorder) [[unlikely]] {
|
||||
crt_.output_sync(LineLayout::EndOfSync);
|
||||
if(display_type_ == Outputs::Display::Type::NTSC60) {
|
||||
crt_.output_colour_burst(LineLayout::EndOfColourBurst - LineLayout::EndOfSync, ColourPhase);
|
||||
} else {
|
||||
crt_.output_default_colour_burst(LineLayout::EndOfColourBurst - LineLayout::EndOfSync);
|
||||
void MC6847Base::sync_and_burst(const int line_begin, const int line_end) {
|
||||
Numeric::if_includes<LineLayout::EndOfColourBurst>(
|
||||
line_begin,
|
||||
line_end,
|
||||
[&] {
|
||||
crt_.output_sync(LineLayout::EndOfSync);
|
||||
if(display_type_ == Outputs::Display::Type::NTSC60) {
|
||||
crt_.output_colour_burst(LineLayout::EndOfColourBurst - LineLayout::EndOfSync, ColourPhase);
|
||||
} else {
|
||||
crt_.output_default_colour_burst(LineLayout::EndOfColourBurst - LineLayout::EndOfSync);
|
||||
}
|
||||
}
|
||||
crt_.output_blank(LineLayout::EndOfLeftBorder - LineLayout::EndOfColourBurst);
|
||||
);
|
||||
}
|
||||
|
||||
pixels_ = reinterpret_cast<uint32_t *>(crt_.begin_data(256));
|
||||
}
|
||||
if(pixels_) [[likely]] {
|
||||
Numeric::clamp<LineLayout::EndOfLeftBorder, LineLayout::EndOfPixels>(
|
||||
line_begin,
|
||||
line_end,
|
||||
void MC6847Base::pixel_line(const int line_begin, const int line_end) {
|
||||
sync_and_burst(line_begin, line_end);
|
||||
Numeric::ActionRange(line_begin, line_end)
|
||||
.clamp<LineLayout::EndOfColourBurst, LineLayout::EndOfLeftBorder>(
|
||||
[&](const int begin, const int end) {
|
||||
crt_.output_level<uint32_t>(end - begin, border_colour_);
|
||||
}
|
||||
)
|
||||
.if_includes<LineLayout::EndOfLeftBorder>(
|
||||
[&] {
|
||||
pixels_ = reinterpret_cast<uint32_t *>(crt_.begin_data(256));
|
||||
}
|
||||
)
|
||||
.clamp<LineLayout::EndOfLeftBorder, LineLayout::EndOfPixels>(
|
||||
[&](const int begin, const int end) {
|
||||
if(!pixels_) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
|
||||
const int row = address_.row();
|
||||
const int column_begin = (begin - LineLayout::EndOfLeftBorder) >> 3;
|
||||
const int column_end = (end - LineLayout::EndOfLeftBorder) >> 3;
|
||||
@@ -295,26 +312,42 @@ void MC6847Base::pixel_line(const int line_begin, const int line_end) {
|
||||
pixels_ += 8;
|
||||
}
|
||||
}
|
||||
)
|
||||
.if_includes<LineLayout::EndOfPixels>(
|
||||
[&] {
|
||||
crt_.output_data(256);
|
||||
}
|
||||
)
|
||||
.clamp<LineLayout::EndOfPixels, LineLayout::EndOfLine>(
|
||||
[&](const int begin, const int end) {
|
||||
crt_.output_level<uint32_t>(end - begin, border_colour_);
|
||||
}
|
||||
)
|
||||
.if_ends_at<LineLayout::EndOfLine>(
|
||||
[&] {
|
||||
address_.apply_hsync();
|
||||
}
|
||||
);
|
||||
}
|
||||
if(line_end == LineLayout::EndOfLine) [[unlikely]] {
|
||||
crt_.output_data(256);
|
||||
address_.apply_hsync();
|
||||
crt_.output_blank(LineLayout::EndOfLine - LineLayout::EndOfPixels);
|
||||
}
|
||||
}
|
||||
|
||||
void MC6847Base::border_line(const int, const int end) {
|
||||
void MC6847Base::border_line(const int line_begin, const int line_end) {
|
||||
sync_and_burst(line_begin, line_end);
|
||||
Numeric::clamp<LineLayout::EndOfColourBurst, LineLayout::EndOfLine>(
|
||||
line_begin,
|
||||
line_end,
|
||||
[&](const int begin, const int end) {
|
||||
crt_.output_level<uint32_t>(end - begin, border_colour_);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void MC6847Base::porch_line(const int, const int end) {
|
||||
if(end == LineLayout::EndOfLine) {
|
||||
crt_.output_sync(LineLayout::EndOfSync);
|
||||
crt_.output_blank(LineLayout::EndOfLine - LineLayout::EndOfSync);
|
||||
}
|
||||
}
|
||||
|
||||
void MC6847Base::porch_line(const int begin, const int end) {
|
||||
border_line(begin, end);
|
||||
}
|
||||
|
||||
void MC6847Base::sync_line(const int, const int end) {
|
||||
if(end == LineLayout::EndOfLine) {
|
||||
crt_.output_sync(LineLayout::EndOfLine);
|
||||
@@ -402,10 +435,14 @@ void MC6847Base::set_mode(
|
||||
address_.target_row_ = repeated_rows(mode);
|
||||
if(is_2bpp(mode)) {
|
||||
mode_ |= Mode::BPP2;
|
||||
border_colour_ = colour_select ? Colours::colour1[0] : Colours::colour0[0];
|
||||
} else {
|
||||
border_colour_ = colour_select ? Colours::resolution1[1] : Colours::resolution0[1];
|
||||
}
|
||||
} else {
|
||||
set_32bytes();
|
||||
address_.target_row_ = 12;
|
||||
border_colour_ = 0;
|
||||
}
|
||||
|
||||
// TODO: apply my net understanding, which is now this:
|
||||
|
||||
@@ -116,6 +116,8 @@ constexpr uint8_t repeated_rows(const GraphicsMode mode) {
|
||||
struct MC6847Base {
|
||||
MC6847Base(Outputs::Display::Type);
|
||||
|
||||
void sync_and_burst(int begin, int end);
|
||||
|
||||
void pixel_line(int begin, int end);
|
||||
void border_line(int begin, int end);
|
||||
void porch_line(int begin, int end);
|
||||
@@ -137,6 +139,7 @@ struct MC6847Base {
|
||||
|
||||
Outputs::CRT::CRT crt_;
|
||||
uint32_t *pixels_ = nullptr;
|
||||
uint32_t border_colour_ = 0;
|
||||
|
||||
void set_mode(
|
||||
bool graphics,
|
||||
|
||||
@@ -80,4 +80,56 @@ void clamp(const int begin, const int end, const FuncT &&function) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls @c function if and only if [begin, end] contains the event point.
|
||||
template <int EventPoint, typename FuncT>
|
||||
void if_includes(const int begin, const int end, const FuncT &&function) {
|
||||
if(begin <= EventPoint && end > EventPoint) {
|
||||
function();
|
||||
}
|
||||
}
|
||||
|
||||
// Provides a factory-method-esque means of chaining potential events across a fixed range
|
||||
// without repeating the range ad nauseam,
|
||||
class ActionRange {
|
||||
public:
|
||||
ActionRange(const int begin, const int end) : begin_(begin), end_(end) {}
|
||||
|
||||
template <int EventPoint, typename FuncT>
|
||||
ActionRange &if_at_start(const FuncT &&function) {
|
||||
if(!begin_) {
|
||||
function();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <int RangeBegin, int RangeEnd, typename FuncT>
|
||||
ActionRange &clamp(const FuncT &&function) {
|
||||
const int range_begin = std::max(begin_, RangeBegin);
|
||||
const int range_end = std::min(end_, RangeEnd);
|
||||
if(range_end > range_begin) {
|
||||
function(range_begin, range_end);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <int EventPoint, typename FuncT>
|
||||
ActionRange &if_includes(const FuncT &&function) {
|
||||
if(begin_ <= EventPoint && end_ > EventPoint) {
|
||||
function();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <int EventPoint, typename FuncT>
|
||||
ActionRange &if_ends_at(const FuncT &&function) {
|
||||
if(end_ == EventPoint) {
|
||||
function();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
int begin_, end_;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user