diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp
index e3c632788..a358de285 100644
--- a/Outputs/CRT/CRT.cpp
+++ b/Outputs/CRT/CRT.cpp
@@ -34,10 +34,11 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di
 	colour_cycle_numerator_ = colour_cycle_numerator;
 	phase_alternates_ = should_alternate;
 	is_alernate_line_ &= phase_alternates_;
+	cycles_per_line_ = cycles_per_line;
 	unsigned int multiplied_cycles_per_line = cycles_per_line * time_multiplier_;
 
-	// generate timing values implied by the given arbuments
-	sync_capacitor_charge_threshold_ = ((int)(syncCapacityLineChargeThreshold * multiplied_cycles_per_line) * 3) / 4;
+	// generate timing values implied by the given arguments
+	sync_capacitor_charge_threshold_ = ((int)(syncCapacityLineChargeThreshold * cycles_per_line) * 3) / 4;
 
 	// create the two flywheels
 	horizontal_flywheel_.reset(new Flywheel(multiplied_cycles_per_line, (millisecondsHorizontalRetraceTime * multiplied_cycles_per_line) >> 6, multiplied_cycles_per_line >> 6));
@@ -113,7 +114,7 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested,
 #define source_phase()				next_run[SourceVertexOffsetOfPhaseTimeAndAmplitude + 0]
 #define source_amplitude()			next_run[SourceVertexOffsetOfPhaseTimeAndAmplitude + 2]
 
-void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Scan::Type type)
+void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bool vsync_requested, const Scan::Type type)
 {
 	std::unique_lock<std::mutex> output_lock = openGL_output_builder_.get_output_lock();
 	number_of_cycles *= time_multiplier_;
@@ -154,13 +155,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo
 		// horizontal counter appropriately
 		number_of_cycles -= next_run_length;
 
-		// either charge or deplete the vertical retrace capacitor (making sure it stops at 0)
-		if(vsync_charging)
-			sync_capacitor_charge_level_ += next_run_length;
-		else
-			sync_capacitor_charge_level_ = std::max(sync_capacitor_charge_level_ - (int)next_run_length, 0);
-//		if(sync_capacitor_charge_level_) printf(":%c %d ", vsync_charging ? '+' : '-', sync_capacitor_charge_level_);
-
 		// react to the incoming event...
 		horizontal_flywheel_->apply_event(next_run_length, (next_run_length == time_until_horizontal_sync_event) ? next_horizontal_sync_event : Flywheel::SyncEvent::None);
 		vertical_flywheel_->apply_event(next_run_length, (next_run_length == time_until_vertical_sync_event) ? next_vertical_sync_event : Flywheel::SyncEvent::None);
@@ -272,16 +266,30 @@ void CRT::advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bo
 void CRT::output_scan(const Scan *const scan)
 {
 	const bool this_is_sync = (scan->type == Scan::Type::Sync);
-	const bool is_trailing_edge = (is_receiving_sync_ && !this_is_sync);
 	const bool is_leading_edge = (!is_receiving_sync_ && this_is_sync);
 	is_receiving_sync_ = this_is_sync;
 
+	// Accumulate: (i) a total of the amount of time in sync; and (ii) the amount of time since sync.
+	if(this_is_sync) { cycles_of_sync_ += scan->number_of_cycles; cycles_since_sync_ = 0; }
+	else cycles_since_sync_ += scan->number_of_cycles;
+
+	bool vsync_requested = false;
+	// If it has been at least half a line since sync ended, then it is safe to decide whether what ended
+	// was vertical sync.
+	if(cycles_since_sync_ > (cycles_per_line_ >> 1))
+	{
+		// If it was vertical sync, set that flag. If it wasn't, clear the summed amount of sync to avoid
+		// a mistaken vertical sync due to an aggregate of horizontals.
+		vsync_requested = (cycles_of_sync_ > sync_capacitor_charge_threshold_);
+		if(vsync_requested || cycles_of_sync_ < (cycles_per_line_ >> 2))
+			cycles_of_sync_ = 0;
+	}
+
 	// This introduces a blackout period close to the expected vertical sync point in which horizontal syncs are not
 	// recognised, effectively causing the horizontal flywheel to freewheel during that period. This attempts to seek
 	// the problem that vertical sync otherwise often starts halfway through a scanline, which confuses the horizontal
 	// flywheel. I'm currently unclear whether this is an accurate solution to this problem.
 	const bool hsync_requested = is_leading_edge && !vertical_flywheel_->is_near_expected_sync();
-	const bool vsync_requested = is_trailing_edge && (sync_capacitor_charge_level_ >= sync_capacitor_charge_threshold_);
 
 	// simplified colour burst logic: if it's within the back porch we'll take it
 	if(scan->type == Scan::Type::ColourBurst)
@@ -299,7 +307,7 @@ void CRT::output_scan(const Scan *const scan)
 	// TODO: inspect raw data for potential colour burst if required
 
 	sync_period_ = is_receiving_sync_ ? (sync_period_ + scan->number_of_cycles) : 0;
-	advance_cycles(scan->number_of_cycles, hsync_requested, vsync_requested, this_is_sync, scan->type);
+	advance_cycles(scan->number_of_cycles, hsync_requested, vsync_requested, scan->type);
 }
 
 /*
diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp
index 559c69a3e..453dbf6a5 100644
--- a/Outputs/CRT/CRT.hpp
+++ b/Outputs/CRT/CRT.hpp
@@ -66,7 +66,7 @@ class CRT {
 		bool is_alernate_line_, phase_alternates_;
 
 		// the outer entry point for dispatching output_sync, output_blank, output_level and output_data
-		void advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Scan::Type type);
+		void advance_cycles(unsigned int number_of_cycles, bool hsync_requested, bool vsync_requested, const Scan::Type type);
 
 		// the inner entry point that determines whether and when the next sync event will occur within
 		// the current output window
@@ -94,6 +94,11 @@ class CRT {
 			enqueued_openGL_functions_.push_back(function);
 		}
 
+		// sync counter, for determining vertical sync
+		unsigned int cycles_of_sync_;
+		unsigned int cycles_since_sync_;
+		unsigned int cycles_per_line_;
+
 	public:
 		/*!	Constructs the CRT with a specified clock rate, height and colour subcarrier frequency.
 			The requested number of buffers, each with the requested number of bytes per pixel,