diff --git a/Z80/Z80.UnitTests/IffTests.cs b/Z80/Z80.UnitTests/IffTests.cs index 27d6ecf..7006e25 100644 --- a/Z80/Z80.UnitTests/IffTests.cs +++ b/Z80/Z80.UnitTests/IffTests.cs @@ -68,19 +68,21 @@ namespace Z80.UnitTests this.cpu.IFF1 = false; this.cpu.IM = 1; - this.cpu.LowerINT(); // pending=true, but IFF1=false - this.cpu.Step(); // pending cleared (IFF1=false), EI runs → IFF1=true + this.cpu.LowerINT(); // but IFF1=false + this.cpu.Step(); // IFF1=false, no interrupt, EI runs → IFF1=true Assert.IsTrue(this.cpu.IFF1, "IFF1 must be true after EI"); - Assert.AreEqual(0x0001, this.cpu.PC.Joined, "No interrupt must fire during EI step"); + Assert.AreEqual(0x0001, this.cpu.PC.Joined, "Normal execution, no interrupt"); - this.cpu.Step(); // NOP at 0x0001 — still no interrupt (pending was cleared) - Assert.AreEqual(0x0002, this.cpu.PC.Joined, "No interrupt must fire on instruction after EI"); + this.cpu.Step(); // IFF1 true, INT still low + Assert.AreEqual(0x0038, this.cpu.PC.Joined, "INT fires if INT is low"); // Produce a new falling edge on INT (raise then lower) to retrigger this.cpu.RaiseINT(); this.cpu.LowerINT(); + + Assert.IsFalse(this.cpu.IFF1, "IFF1 has been disabled by the INT handler"); this.cpu.Step(); - Assert.AreEqual(0x0038, this.cpu.PC.Joined, "INT must fire after new falling edge post-EI"); + Assert.AreEqual(0x0038, this.cpu.PC.Joined - 1, "Inside INT handled at 0x38"); } [TestMethod] diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 8e37210..767aff8 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -17,12 +17,8 @@ namespace Z80 this.UpdateRegisterBank(); this.UpdateAFBank(); this.RaisedPOWER += this.Z80_RaisedPOWER; - this.LoweredNMI += this.Z80_LoweredNMI; - this.LoweredINT += this.Z80_LoweredINT; } - private bool _interruptPending; - private bool _nonMaskableInterruptPending; private readonly InputOutput _ports; @@ -185,15 +181,14 @@ namespace Z80 this.HandleRESET(); return; } - else if (this._nonMaskableInterruptPending) + else if (this._nonMaskableInterruptTriggered) { - this._nonMaskableInterruptPending = false; + this._nonMaskableInterruptTriggered = false; this.HandleNMI(); return; } - else if (this._interruptPending) + else if (this.INT.Lowered()) { - this._interruptPending = false; if (this.IFF1) { this.HandleINT(); @@ -247,14 +242,16 @@ namespace Z80 this.ResetRegisterSet(); } - private void Z80_LoweredINT(object? sender, EventArgs e) => this._interruptPending = true; + //private void Z80_LoweredINT(object? sender, EventArgs e) => this._interruptPending = true; - private void Z80_LoweredNMI(object? sender, EventArgs e) => this._nonMaskableInterruptPending = true; + //private void Z80_LoweredNMI(object? sender, EventArgs e) => this._nonMaskableInterruptPending = true; #region Z80 specific pins #region NMI pin + private bool _nonMaskableInterruptTriggered; + public event EventHandler? RaisingNMI; public event EventHandler? RaisedNMI; @@ -284,6 +281,7 @@ namespace Z80 { LoweringNMI?.Invoke(this, EventArgs.Empty); this.NMI.Lower(); + this._nonMaskableInterruptTriggered = true; LoweredNMI?.Invoke(this, EventArgs.Empty); } }