diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 6778c6187..8aa0c4e6c 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -99,8 +99,12 @@ HalfCycles Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &c } break; case CPU::Z80::PartialMachineCycle::Interrupt: + // resetting event is M1 and IOREQ both simultaneously having leading edges; + // that happens 2 cycles before the end of INTACK. So the timer was reset and + // now has advanced twice. + horizontal_counter_ = HalfCycles(2); + *cycle.value = 0xff; - horizontal_counter_ = 0; break; case CPU::Z80::PartialMachineCycle::Refresh: @@ -109,7 +113,7 @@ HalfCycles Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &c // final two cycles of an opcode fetch. Therefore communicate a transient signalling // of the IRQ line if necessary. if(!(address & 0x40)) { - set_interrupt_line(true, -2); + set_interrupt_line(true, Cycles(-2)); set_interrupt_line(false); } if(has_latched_video_byte_) { @@ -126,8 +130,7 @@ HalfCycles Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &c } break; - case CPU::Z80::PartialMachineCycle::ReadOpcodeStart: - case CPU::Z80::PartialMachineCycle::ReadOpcodeWait: + case CPU::Z80::PartialMachineCycle::ReadOpcode: // Check for use of the fast tape hack. if(use_fast_tape_hack_ && address == tape_trap_address_ && tape_player_.has_tape()) { uint64_t prior_offset = tape_player_.get_tape()->get_offset(); diff --git a/Processors/Z80/Z80.hpp b/Processors/Z80/Z80.hpp index ce4165264..bf6eae7d9 100644 --- a/Processors/Z80/Z80.hpp +++ b/Processors/Z80/Z80.hpp @@ -104,7 +104,7 @@ struct PartialMachineCycle { return operation <= Operation::BusAcknowledge; } inline bool is_wait() const { - return operation >= Operation::ReadWait && operation <= Operation::InterruptWait; + return operation >= Operation::ReadOpcodeWait && operation <= Operation::InterruptWait; } }; @@ -1894,7 +1894,7 @@ template class Processor { how many cycles before now the line changed state. The value may not be longer than the current machine cycle. If called at any other time, this must be zero. */ - void set_interrupt_line(bool value, int offset = 0) { + void set_interrupt_line(bool value, HalfCycles offset = 0) { if(irq_line_ == value) return; // IRQ requests are level triggered and masked. @@ -1908,7 +1908,7 @@ template class Processor { // If this change happened at least one cycle ago then: (i) we're promised that this is a machine // cycle per the contract on supplying an offset; and (ii) that means it happened before the lines // were sampled. So adjust the most recent sample. - if(offset < 0) { + if(offset <= HalfCycles(-2)) { last_request_status_ = (last_request_status_ & ~Interrupt::IRQ) | (request_status_ & Interrupt::IRQ); } }