From 257420b0f7fdc96162239777db35c640df315975 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Tue, 10 May 2016 19:04:03 -0400
Subject: [PATCH] Fixed potential output error if buffer top were hit;
 clarified buffer size constants.

---
 Outputs/CRT/CRT.cpp                    | 34 ++++++++++++--------------
 Outputs/CRT/CRT.hpp                    |  9 +++++--
 Outputs/CRT/Internals/CRTConstants.hpp |  4 +--
 3 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp
index 712823fc1..74c50d7e4 100644
--- a/Outputs/CRT/CRT.cpp
+++ b/Outputs/CRT/CRT.cpp
@@ -69,8 +69,7 @@ CRT::CRT(unsigned int common_output_divisor) :
 	_common_output_divisor(common_output_divisor),
 	_is_writing_composite_run(false),
 	_delegate(nullptr),
-	_frames_since_last_delegate_call(0),
-	_did_start_run(false) {}
+	_frames_since_last_delegate_call(0) {}
 
 CRT::CRT(unsigned int cycles_per_line, unsigned int common_output_divisor, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int buffer_depth) : CRT(common_output_divisor)
 {
@@ -187,29 +186,26 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
 		if(needs_endpoint)
 		{
 			if(
-				_is_writing_composite_run == _did_start_run &&
 				_openGL_output_builder->composite_output_run_has_room_for_vertex() &&
 				!_openGL_output_builder->composite_output_buffer_is_full())
 			{
-				uint8_t *next_run = _openGL_output_builder->get_next_output_run();
-				if(next_run)
+				if(!_is_writing_composite_run)
 				{
-					if(_did_start_run)
-					{
-						output_x1() = (uint16_t)_horizontal_flywheel->get_current_output_position();
-						output_position_y() = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
-						output_tex_y() = _openGL_output_builder->get_composite_output_y();
-					}
-					else
-					{
-						output_x2() = (uint16_t)_horizontal_flywheel->get_current_output_position();
-						_openGL_output_builder->complete_output_run();
-					}
-
-					_did_start_run ^= true;
+					_output_run.x1 = (uint16_t)_horizontal_flywheel->get_current_output_position();
+					_output_run.y = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
+					_output_run.tex_y = _openGL_output_builder->get_composite_output_y();
 				}
+				else
+				{
+					uint8_t *next_run = _openGL_output_builder->get_next_output_run();
+					output_x1() = _output_run.x1;
+					output_position_y() = _output_run.y;
+					output_tex_y() = _output_run.tex_y;
+					output_x2() = (uint16_t)_horizontal_flywheel->get_current_output_position();
+					_openGL_output_builder->complete_output_run();
+				}
+				_is_writing_composite_run ^= true;
 			}
-			_is_writing_composite_run ^= true;
 		}
 
 		if(next_run_length == time_until_horizontal_sync_event && next_horizontal_sync_event == Flywheel::SyncEvent::StartRetrace)
diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp
index 3ea5858ab..a38e63795 100644
--- a/Outputs/CRT/CRT.hpp
+++ b/Outputs/CRT/CRT.hpp
@@ -68,7 +68,7 @@ class CRT {
 
 		uint8_t _colour_burst_phase, _colour_burst_amplitude;
 		uint16_t _colour_burst_time;
-		bool _is_writing_composite_run, _did_start_run;
+		bool _is_writing_composite_run;
 
 		// the outer entry point for dispatching output_sync, output_blank, output_level and output_data
 		void advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Scan::Type type, uint16_t tex_x, uint16_t tex_y);
@@ -81,7 +81,12 @@ class CRT {
 		// OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here.
 		std::unique_ptr<OpenGLOutputBuilder> _openGL_output_builder;
 
-		// The delegate;
+		// temporary storage used during the construction of output runs
+		struct {
+			uint16_t x1, y, tex_y;
+		} _output_run;
+
+		// The delegate
 		Delegate *_delegate;
 		unsigned int _frames_since_last_delegate_call;
 
diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp
index bcf6c5385..e1c8a3207 100644
--- a/Outputs/CRT/Internals/CRTConstants.hpp
+++ b/Outputs/CRT/Internals/CRTConstants.hpp
@@ -40,8 +40,8 @@ const GLsizei IntermediateBufferWidth = 2048;
 const GLsizei IntermediateBufferHeight = 1024;
 
 // Some internal buffer sizes
-const GLsizeiptr OutputVertexBufferDataSize = 8 * IntermediateBufferHeight;			// likely always to be OutputVertexSize * IntermediateBufferHeight, that being the maximum number of scans of output that can be created between draws
-const GLsizeiptr SourceVertexBufferDataSize = 2 * 16 * IntermediateBufferHeight * 2;	// a multiple of 2 * SourceVertexSize
+const GLsizeiptr OutputVertexBufferDataSize = OutputVertexSize * IntermediateBufferHeight;		// i.e. the maximum number of scans of output that can be created between draws
+const GLsizeiptr SourceVertexBufferDataSize = 2 * SourceVertexSize * IntermediateBufferHeight * 2;	// a multiple of 2 * SourceVertexSize
 
 }
 }