From 6e034c9b7f82ea285c53b2877c80c766935f48d0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 11 Aug 2021 20:31:37 -0400 Subject: [PATCH] At least manages to place a pixel region on screen. Albeit that I've suddenly realised that I've failed properly to think about high-res versus low-res. --- Machines/Amiga/Chipset.cpp | 68 +++++++++++++++++++++++++++++++++----- Machines/Amiga/Chipset.hpp | 14 ++++++-- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 0aaeed41b..cfa83627e 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -206,20 +206,67 @@ template void Chipset::output() { LINK(burst, output_default_colour_burst, burst - blank2); // TODO: only if colour enabled. LINK(blank3, output_blank, blank3 - burst); - // Output colour 0 to fill the rest of the line; Kickstart uses this - // colour to post the error code. TODO: actual pixels, etc. - if(cycle == line_length_ - 1) { - uint16_t *const pixels = reinterpret_cast(crt_.begin_data(1)); - if(pixels) { - *pixels = palette_[0]; + display_horizontal_ |= (cycle*2) == fetch_window_[0]; + display_horizontal_ &= (cycle*2) != fetch_window_[1]; + + if constexpr (cycle > blank3) { + const bool is_pixel_display = display_horizontal_ && fetch_vertical_; + + if( + (is_pixel_display == is_border_) || + (is_border_ && border_colour_ != palette_[0])) { + flush_output(); + + is_border_ = !is_pixel_display; + border_colour_ = palette_[0]; + } + + if(is_pixel_display) { + if(!pixels_) { + uint16_t *const new_pixels = reinterpret_cast(crt_.begin_data(4 * size_t(line_length_ - cycle))); + if(new_pixels) { + flush_output(); + } + pixels_ = new_pixels; + } + + if(pixels_) { + pixels_[0] = 0xffff; + pixels_[1] = 0x0000; + pixels_[2] = 0xffff; + pixels_[3] = 0x0000; + pixels_ += 4; + } + } + ++zone_duration_; + + // Output the rest of the line. TODO: optimise border area. + if(cycle == line_length_ - 1) { + flush_output(); } - crt_.output_data((cycle - blank3) * 4, 1); } } #undef LINK } +void Chipset::flush_output() { + if(!zone_duration_) return; + + if(is_border_) { + uint16_t *const pixels = reinterpret_cast(crt_.begin_data(1)); + if(pixels) { + *pixels = border_colour_; + } + crt_.output_data(zone_duration_ * 4, 1); + } else { + crt_.output_data(zone_duration_ * 4); + } + zone_duration_ = 0; + pixels_ = nullptr; +} + + template bool Chipset::perform_cycle() { constexpr auto BlitterFlag = DMAMask::value; constexpr auto BitplaneFlag = DMAMask::value; @@ -229,8 +276,8 @@ template bool Chipset::perform_cycle() { // Update state as to whether bitplane fetching should happen now. // // TODO: figure out how the hard stops factor into this. - fetch_horizontal_ |= cycle == display_window_start_[0]; - fetch_horizontal_ &= cycle != display_window_stop_[0]; + fetch_horizontal_ |= cycle == fetch_window_[0]; + fetch_horizontal_ &= cycle != fetch_window_[1]; // Top priority: bitplane collection. if((dma_control_ & BitplaneFlag) == BitplaneFlag) { @@ -361,6 +408,9 @@ template Chipset::Changes Chipset::run(HalfCycles length) { did_fetch_ = false; } + std::fill(even_playfield_.begin(), even_playfield_.end(), 0); + std::fill(odd_playfield_.begin(), odd_playfield_.end(), 0); + if(y_ == frame_height_) { ++changes.vsyncs; interrupt_requests_ |= InterruptMask::value; diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 346848203..b03fa36b4 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -169,8 +169,16 @@ class Chipset { // Ephemeral bitplane collection state. bool fetch_vertical_ = false, fetch_horizontal_ = false; + bool display_horizontal_ = false; bool did_fetch_ = false; + // Output state. + uint16_t border_colour_ = 0; + bool is_border_ = true; + int zone_duration_ = 0; + uint16_t *pixels_ = nullptr; + void flush_output(); + using BitplaneData = std::array; class Bitplanes: public DMADevice<6> { @@ -184,15 +192,15 @@ class Chipset { private: bool is_high_res_ = false; int collection_offset_ = 0; - int plane_count_ = 1; + int plane_count_ = 0; BitplaneData next; } bitplanes_; void post_bitplanes(const BitplaneData &data); - uint8_t even_playfield_[912]; - uint8_t odd_playfield_[912]; + std::array even_playfield_; + std::array odd_playfield_; int odd_delay_ = 0, even_delay_ = 0; // MARK: - Copper.