From 8ccec37a4b55fca7d370877175760ec55c1aa39a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 9 Jul 2017 19:11:38 -0400 Subject: [PATCH 1/2] Eliminated a further potential cause of texture/geometry mismatch: the texture retain succeeded but then there wasn't room for geometry. --- Outputs/CRT/CRT.cpp | 3 +++ Outputs/CRT/Internals/TextureBuilder.cpp | 5 +++++ Outputs/CRT/Internals/TextureBuilder.hpp | 3 +++ 3 files changed, 11 insertions(+) diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index b14a30ebe..e612dab5e 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -143,6 +143,9 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo bool did_retain_source_data = openGL_output_builder_.texture_builder.retain_latest(); if(did_retain_source_data) { next_run = openGL_output_builder_.array_builder.get_input_storage(SourceVertexSize); + if(!next_run) { + openGL_output_builder_.texture_builder.discard_latest(); + } } } diff --git a/Outputs/CRT/Internals/TextureBuilder.cpp b/Outputs/CRT/Internals/TextureBuilder.cpp index 1df076afc..7fa46d955 100644 --- a/Outputs/CRT/Internals/TextureBuilder.cpp +++ b/Outputs/CRT/Internals/TextureBuilder.cpp @@ -128,6 +128,11 @@ bool TextureBuilder::retain_latest() { return true; } +void TextureBuilder::discard_latest() { + if(was_full_) return; + number_of_write_areas_--; +} + bool TextureBuilder::is_full() { return is_full_; } diff --git a/Outputs/CRT/Internals/TextureBuilder.hpp b/Outputs/CRT/Internals/TextureBuilder.hpp index bf2da997d..476e1d04b 100644 --- a/Outputs/CRT/Internals/TextureBuilder.hpp +++ b/Outputs/CRT/Internals/TextureBuilder.hpp @@ -79,6 +79,9 @@ class TextureBuilder { /// @returns @c true if a retain succeeded; @c false otherwise. bool retain_latest(); + // Undoes the most recent retain_latest. Undefined behaviour if a submission has occurred in the interim. + void discard_latest(); + /// @returns @c true if all future calls to @c allocate_write_area will fail on account of the input texture /// being full; @c false if calls may succeed. bool is_full(); From ed28260aaff659a05aefa5428b43f5e0c9708d02 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 9 Jul 2017 19:33:05 -0400 Subject: [PATCH 2/2] Hardens the ZX80/81 video routines to ensure they never try to push data into the future and don't double-count time when pixels would ostensibly run into sync. You could previously see the CRT being handed negative run lengths if sync interrupted pixels or if a run of more than 320 pixels (my arbitrary buffer size) occurred, with corresponding poor behaviour given my use of unsigned numbers. --- Machines/ZX8081/Video.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Machines/ZX8081/Video.cpp b/Machines/ZX8081/Video.cpp index 0f9f64b0c..5531e7dee 100644 --- a/Machines/ZX8081/Video.cpp +++ b/Machines/ZX8081/Video.cpp @@ -50,9 +50,10 @@ void Video::flush(bool next_sync) { // sync, or if we're past its end anyway. Otherwise let it be. unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_); if(data_length < cycles_since_update_ || next_sync) { - crt_->output_data(data_length, 1); + unsigned int output_length = std::min(data_length, cycles_since_update_); + crt_->output_data(output_length, 1); line_data_pointer_ = line_data_ = nullptr; - cycles_since_update_ -= data_length; + cycles_since_update_ -= output_length; } else return; } @@ -86,19 +87,20 @@ void Video::output_byte(uint8_t byte) { // If a buffer was obtained, serialise the new pixels. if(line_data_) { + // If the buffer is full, output it now and obtain a new one + if(line_data_pointer_ - line_data_ == 320) { + crt_->output_data(320, 1); + cycles_since_update_ -= 320; + line_data_pointer_ = line_data_ = crt_->allocate_write_area(320); + if(!line_data_) return; + } + uint8_t mask = 0x80; for(int c = 0; c < 8; c++) { line_data_pointer_[c] = (byte & mask) ? 0xff : 0x00; mask >>= 1; } line_data_pointer_ += 8; - - // If that fills the buffer, output it now. - if(line_data_pointer_ - line_data_ == 320) { - crt_->output_data(320, 1); - line_data_pointer_ = line_data_ = nullptr; - cycles_since_update_ -= 160; - } } }