1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-03 11:30:02 +00:00

Push HSYNC 11 slots over, to its proper position, and add a frame crop.

This commit is contained in:
Thomas Harte 2021-11-20 12:39:50 -05:00
parent a94b4f62fd
commit ff68b26c44

View File

@ -89,6 +89,9 @@ Chipset::Chipset(MemoryMap &map, int input_clock_rate) :
joysticks_.emplace_back(new Joystick());
cia_a_handler_.set_joystick(&joystick(0));
// Very conservatively crop, to roughly the centre 90% of a frame.
crt_.set_visible_area(Outputs::Display::Rect(0.05f, 0.045f, 0.9f, 0.9f));
}
#undef DMA_CONSTRUCT
@ -132,20 +135,6 @@ template <int cycle> void Chipset::output() {
// => 184 windows out of 227 are visible, which concurs.
//
// A complete from-thin-air guess:
//
// 7 cycles blank;
// 17 cycles sync;
// 3 cycles blank;
// 9 cycles colour burst;
// 7 cycles blank.
constexpr int blank1 = 7;
constexpr int sync = 17 + blank1;
constexpr int blank2 = 3 + sync;
constexpr int burst = 9 + blank2;
constexpr int blank3 = 7 + burst;
static_assert(blank3 == 43);
// Advance audio.
audio_.output();
@ -171,15 +160,44 @@ template <int cycle> void Chipset::output() {
}
}
//
// Horizontal sync: HC18HC35;
// Horizontal blank: HC15HC53.
//
// Beyond that: guesswork.
//
// So, from cycle 0:
//
// 15 cycles border/pixels;
// 3 cycles blank;
// 17 cycles sync;
// 3 cycles blank;
// 9 cycles colour burst;
// 6 cycles blank;
// then more border/pixels to end of line.
//
// (???)
constexpr int end_of_pixels = 15;
constexpr int blank1 = 3 + end_of_pixels;
constexpr int sync = 17 + blank1;
constexpr int blank2 = 3 + sync;
constexpr int burst = 9 + blank2;
constexpr int blank3 = 6 + burst;
static_assert(blank3 == 53);
#define LINK(location, action, length) \
if(cycle == (location)) { \
crt_.action((length) * 4); \
}
if(y_ < vertical_blank_height_) {
if(!cycle) {
flush_output();
}
// Put three lines of sync at the centre of the vertical blank period.
// Offset by half a line if interlaced and on an odd frame.
const int midline = vertical_blank_height_ >> 1;
if(is_long_field_) {
if(y_ < midline - 1 || y_ > midline + 2) {
@ -209,18 +227,22 @@ template <int cycle> void Chipset::output() {
}
}
} else {
// TODO: incorporate the lowest display window bits elsewhere.
display_horizontal_ |= cycle == (display_window_start_[0] >> 1);
display_horizontal_ &= cycle != (display_window_stop_[0] >> 1);
if(cycle == end_of_pixels) {
flush_output();
}
// Output the correct sequence of blanks, syncs and burst atomically.
LINK(blank1, output_blank, blank1);
LINK(blank1, output_blank, blank1 - end_of_pixels);
LINK(sync, output_sync, sync - blank1);
LINK(blank2, output_blank, blank2 - sync);
LINK(burst, output_default_colour_burst, burst - blank2); // TODO: only if colour enabled.
LINK(blank3, output_blank, blank3 - burst);
// TODO: incorporate the lowest display window bits elsewhere.
display_horizontal_ |= cycle == (display_window_start_[0] >> 1);
display_horizontal_ &= cycle != (display_window_stop_[0] >> 1);
if constexpr (cycle > blank3) {
if constexpr (cycle < end_of_pixels || cycle > blank3) {
const bool is_pixel_display = display_horizontal_ && fetch_vertical_;
if(
@ -234,7 +256,7 @@ template <int cycle> void Chipset::output() {
if(is_pixel_display) {
if(!pixels_) {
uint16_t *const new_pixels = reinterpret_cast<uint16_t *>(crt_.begin_data(4 * size_t(line_length_ - cycle)));
uint16_t *const new_pixels = reinterpret_cast<uint16_t *>(crt_.begin_data(4 * size_t(line_length_ + end_of_pixels - cycle)));
if(new_pixels) {
flush_output();
}
@ -242,11 +264,18 @@ template <int cycle> void Chipset::output() {
}
if(pixels_) {
// TODO: this doesn't support dual playfields; use an alternative
// palette table for that?
// TODO:
//
// (1) dump bit 5 of a six-bitplane playfield if this Chipset doesn't support extra half-bright.
// (2) priorities, in general;
// (3) collisions;
// (4) a much less dense implementation. In particular: map from [16]-bit input to present or
// absent flags, use those to update collisions and then to index a mask table for compositing.
// Which would mean getting through the whole ordeal without branching... as soon as I come up
// with a branchless method for priorities. Hmmmm.
const uint32_t source = bitplane_pixels_.get(is_high_res_);
// TODO: dump bit 5 if this Chipset doesn't support extra half-bright.
// TODO:
if(dual_playfields_) {
// Dense: just write both.
if(even_over_odd_) {
@ -315,13 +344,9 @@ template <int cycle> void Chipset::output() {
}
}
++zone_duration_;
// Output the rest of the line. TODO: optimise border area.
if(cycle == line_length_ - 1) {
flush_output();
}
}
}
#undef LINK
// Update all active pixel shifters.
bitplane_pixels_.shift(is_high_res_);
@ -341,8 +366,6 @@ template <int cycle> void Chipset::output() {
);
previous_bitplanes_ = next_bitplanes_;
}
#undef LINK
}
void Chipset::flush_output() {