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() {