diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp
index 02df50f4b..aec0a447b 100644
--- a/Machines/ColecoVision/ColecoVision.cpp
+++ b/Machines/ColecoVision/ColecoVision.cpp
@@ -198,8 +198,19 @@ class ConcreteMachine:
 
 		// MARK: Z80::BusHandler
 		forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
-			time_since_vdp_update_ += cycle.length;
-			time_since_sn76489_update_ += cycle.length;
+			// The SN76489 will use its ready line to trigger the Z80's wait for three
+			// cycles when accessed. Everything else runs at full speed. Short-circuit
+			// that whole piece of communications by just accruing the time here if applicable.
+			const HalfCycles penalty(
+				(
+					cycle.operation == CPU::Z80::PartialMachineCycle::Output &&
+					((*cycle.address >> 5) & 7) == 7
+				) ? 6 : 0
+			);
+			const HalfCycles length = cycle.length + penalty;
+
+			time_since_vdp_update_ += length;
+			time_since_sn76489_update_ += length;
 
 			uint16_t address = cycle.address ? *cycle.address : 0x0000;
 			switch(cycle.operation) {
@@ -329,13 +340,13 @@ class ConcreteMachine:
 			}
 
 			if(time_until_interrupt_ > 0) {
-				time_until_interrupt_ -= cycle.length;
+				time_until_interrupt_ -= length;
 				if(time_until_interrupt_ <= HalfCycles(0)) {
 					z80_.set_non_maskable_interrupt_line(true, time_until_interrupt_);
 				}
 			}
 
-			return HalfCycles(0);
+			return penalty;
 		}
 
 		void flush() {