From abe47b6ed8aa09930dea33dd709c1e621dc335d9 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 15 Apr 2018 18:00:40 -0400 Subject: [PATCH] Makes first attempt at a stable display area. Not entirely successful. --- Machines/AppleII/Video.cpp | 71 ++++++++++++++++++++++++++++++++++++-- Machines/AppleII/Video.hpp | 4 +++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Machines/AppleII/Video.cpp b/Machines/AppleII/Video.cpp index 45418760a..92209fc1f 100644 --- a/Machines/AppleII/Video.cpp +++ b/Machines/AppleII/Video.cpp @@ -22,16 +22,81 @@ Video::Video() : "return float(texValue & 128u);" "}"); - // Show only the centre 80% of the TV frame. + // Show only the centre 75% of the TV frame. crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite); - crt_->set_visible_area(Outputs::CRT::Rect(0.1f, 0.1f, 0.8f, 0.8f)); + crt_->set_visible_area(Outputs::CRT::Rect(0.115f, 0.115f, 0.77f, 0.77f)); } Outputs::CRT::CRT *Video::get_crt() { return crt_.get(); } -void Video::run_for(const Cycles) { +void Video::run_for(const Cycles cycles) { + /* + Addressing scheme used throughout is that column 0 is the first column with pixels in it; + row 0 is the first row with pixels in it. + + A frame is oriented around 65 cycles across, 262 lines down. + */ + const int first_sync_line = 220; // A complete guess. Information needed. + const int first_sync_column = 49; // Also a guess. + + int int_cycles = cycles.as_int(); + while(int_cycles) { + const int cycles_this_line = std::min(65 - column_, int_cycles); + + if(row_ >= first_sync_line && row_ < first_sync_line + 3) { + crt_->output_sync(static_cast(cycles_this_line) * 7); + } else { + const int ending_column = column_ + cycles_this_line; + + if(column_ < 40) { + if(row_ < 192) { + if(!column_) { + pixel_pointer_ = crt_->allocate_write_area(40); + } + + // TODO: actually store pixels. + + if(ending_column >= 40) { + for(int c = 0; c < 40; ++c) { + pixel_pointer_[c] = 0xaa; + } + crt_->output_data(280, 7); + } + } else { + if(ending_column >= 40) { + crt_->output_blank(280); + } + } + } + + const int first_blank_start = std::max(40, column_); + const int first_blank_end = std::min(first_sync_column, ending_column); + if(first_blank_end > first_blank_start) { + crt_->output_blank(static_cast(first_blank_end - first_blank_start) * 7); + } + + // TODO: colour burst. + + const int sync_start = std::max(first_sync_column, column_); + const int sync_end = std::min(first_sync_column + 4, ending_column); + if(sync_end > sync_start) { + crt_->output_sync(static_cast(sync_end - sync_start) * 7); + } + + const int second_blank_start = std::max(first_sync_column + 4, column_); + if(ending_column > second_blank_start) { + crt_->output_blank(static_cast(ending_column - second_blank_start) * 7); + } + } + + int_cycles -= cycles_this_line; + column_ = (column_ + cycles_this_line) % 65; + if(!column_) { + row_ = (row_ + 1) % 262; + } + } } void Video::set_graphics_mode() { diff --git a/Machines/AppleII/Video.hpp b/Machines/AppleII/Video.hpp index 2a24b8769..999bc12e0 100644 --- a/Machines/AppleII/Video.hpp +++ b/Machines/AppleII/Video.hpp @@ -38,6 +38,10 @@ class Video { private: std::unique_ptr crt_; + + int video_page_ = 0; + int row_ = 0, column_ = 0; + uint8_t *pixel_pointer_ = nullptr; }; }