From b3f4d0ed8cb2da34f4597c06ca25d8f173d891dc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 16 May 2018 19:06:03 -0400 Subject: [PATCH] Imposes a three-cycle penalty for SN76489 access. This is my reading of (i) the SN76489 data sheet; plus (ii) the ColecoVision schematic. --- Machines/ColecoVision/ColecoVision.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) 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() {