Turns out using lambdas to control pins is lovely and correct, but terribly slow. Back to a more traditional method.

This commit is contained in:
Adrian Conlon
2025-03-24 20:18:04 +00:00
parent d4dc99b454
commit 3d6b549c76
12 changed files with 184 additions and 326 deletions

View File

@@ -14,7 +14,6 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.Bus.Poke(address, value.High);
this.Bus.Poke(++address, value.Low);
}
@@ -51,14 +50,12 @@ namespace EightBit
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.Push(value.Low);
this.Push(value.High);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.High);
++this.Bus.Address.Word;
this.MemoryWrite(value.Low);
@@ -66,7 +63,6 @@ namespace EightBit
protected override void SetWordPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.High);
++this.Bus.Address.Low;
this.MemoryWrite(value.Low);

View File

@@ -28,7 +28,6 @@ namespace EightBit
public byte Peek(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return this.Peek(absolute.Word);
}
@@ -38,7 +37,6 @@ namespace EightBit
public void Poke(Register16 absolute, byte value)
{
ArgumentNullException.ThrowIfNull(absolute);
this.Poke(absolute.Word, value);
}
@@ -58,7 +56,6 @@ namespace EightBit
public byte Read(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return this.Read(absolute.Low, absolute.High);
}
@@ -89,7 +86,6 @@ namespace EightBit
public void Write(Register16 absolute, byte value)
{
ArgumentNullException.ThrowIfNull(absolute);
this.Write(absolute.Low, absolute.High, value);
}
@@ -133,7 +129,6 @@ namespace EightBit
protected ref byte Reference(Register16 absolute)
{
ArgumentNullException.ThrowIfNull(absolute);
return ref this.Reference(absolute.Word);
}

View File

@@ -25,9 +25,9 @@ namespace EightBit
{
if (this.POWER.Lowered())
{
this.OnRaisingPOWER();
RaisingPOWER?.Invoke(this, EventArgs.Empty);
this.POWER.Raise();
this.OnRaisedPOWER();
RaisedPOWER?.Invoke(this, EventArgs.Empty);
}
}
@@ -35,18 +35,10 @@ namespace EightBit
{
if (this.POWER.Raised())
{
this.OnLoweringPOWER();
LoweringPOWER?.Invoke(this, EventArgs.Empty);
this.POWER.Lower();
this.OnLoweredPOWER();
LoweredPOWER?.Invoke(this, EventArgs.Empty);
}
}
protected virtual void OnRaisingPOWER() => RaisingPOWER?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedPOWER() => RaisedPOWER?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringPOWER() => LoweringPOWER?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredPOWER() => LoweredPOWER?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -7,7 +7,7 @@
<GenerateDocumentationFile>False</GenerateDocumentationFile>
<SignAssembly>False</SignAssembly>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<AnalysisLevel>latest-all</AnalysisLevel>
<AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -20,6 +20,7 @@ namespace EightBit
{
this._decodedOpCodes[i] = new((byte)i);
}
this.RaisedPOWER += this.IntelProcessor_RaisedPOWER;
}
public event EventHandler<EventArgs>? RaisingHALT;
@@ -67,9 +68,10 @@ namespace EightBit
{
if (this.HALT.Lowered())
{
this.OnRaisingHALT();
RaisingHALT?.Invoke(this, EventArgs.Empty);
this.HALT.Raise();
this.OnRaisedHALT();
++this.PC.Word; // Release the PC from HALT instruction
RaisedHALT?.Invoke(this, EventArgs.Empty);
}
}
@@ -77,9 +79,10 @@ namespace EightBit
{
if (this.HALT.Raised())
{
this.OnLoweringHALT();
LoweringHALT?.Invoke(this, EventArgs.Empty);
this.HALT.Lower();
this.OnLoweredHALT();
--this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
LoweredHALT?.Invoke(this, EventArgs.Empty);
}
}
@@ -102,27 +105,10 @@ namespace EightBit
return HalfCarryTableSub[index & (int)Mask.Three];
}
protected override void OnRaisedPOWER()
private void IntelProcessor_RaisedPOWER(object? sender, EventArgs e)
{
this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Sixteen;
this.RaiseHALT();
base.OnRaisedPOWER();
}
protected virtual void OnRaisingHALT() => RaisingHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedHALT()
{
++this.PC.Word; // Release the PC from HALT instruction
RaisedHALT?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnLoweringHALT() => LoweringHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredHALT()
{
--this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
LoweredHALT?.Invoke(this, EventArgs.Empty);
}
protected override void HandleRESET()

View File

@@ -15,7 +15,6 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.Bus.Poke(address, value.Low);
this.Bus.Poke(++address, value.High);
}
@@ -52,14 +51,12 @@ namespace EightBit
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.Push(value.High);
this.Push(value.Low);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.Low);
++this.Bus.Address.Word;
this.MemoryWrite(value.High);
@@ -67,7 +64,6 @@ namespace EightBit
protected override void SetWordPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.Low);
++this.Bus.Address.Low;
this.MemoryWrite(value.High);

View File

@@ -10,57 +10,9 @@ namespace EightBit
public event EventHandler<EventArgs>? ExecutingInstruction;
public event EventHandler<EventArgs>? ExecutedInstruction;
protected virtual void OnExecutedInstruction() => ExecutedInstruction?.Invoke(this, EventArgs.Empty);
protected virtual void OnExecutingInstruction() => ExecutingInstruction?.Invoke(this, EventArgs.Empty);
#endregion
#region Bus events
#region Memory events
#region Memory read events
public event EventHandler<EventArgs>? ReadingMemory;
public event EventHandler<EventArgs>? ReadMemory;
protected virtual void OnReadingMemory() => ReadingMemory?.Invoke(this, EventArgs.Empty);
protected virtual void OnReadMemory() => ReadMemory?.Invoke(this, EventArgs.Empty);
#endregion
#region Memory write events
public event EventHandler<EventArgs>? WritingMemory;
public event EventHandler<EventArgs>? WrittenMemory;
protected virtual void OnWritingMemory() => WritingMemory?.Invoke(this, EventArgs.Empty);
protected virtual void OnWrittenMemory() => WrittenMemory?.Invoke(this, EventArgs.Empty);
#endregion
#endregion
#region IO events
#region IO read events
public event EventHandler<EventArgs>? ReadingIO;
public event EventHandler<EventArgs>? ReadIO;
protected virtual void OnReadingIO() => ReadingIO?.Invoke(this, EventArgs.Empty);
protected virtual void OnReadIO() => ReadIO?.Invoke(this, EventArgs.Empty);
#endregion
#region IO write events
public event EventHandler<EventArgs>? WritingIO;
public event EventHandler<EventArgs>? WrittenIO;
protected virtual void OnWritingIO() => WritingIO?.Invoke(this, EventArgs.Empty);
protected virtual void OnWrittenIO() => WrittenIO?.Invoke(this, EventArgs.Empty);
#endregion
#endregion
#endregion
private PinLevel _resetLine;
private PinLevel _intLine;
@@ -108,12 +60,12 @@ namespace EightBit
public virtual int Step()
{
this.ResetCycles();
this.OnExecutingInstruction();
ExecutingInstruction?.Invoke(this, EventArgs.Empty);
if (this.Powered)
{
this.PoweredStep();
}
this.OnExecutedInstruction();
ExecutedInstruction?.Invoke(this, EventArgs.Empty);
return this.Cycles;
}
@@ -149,9 +101,9 @@ namespace EightBit
{
if (this.RESET.Lowered())
{
this.OnRaisingRESET();
RaisingRESET?.Invoke(this, EventArgs.Empty);
this.RESET.Raise();
this.OnRaisedRESET();
RaisedRESET?.Invoke(this, EventArgs.Empty);
}
}
@@ -159,9 +111,9 @@ namespace EightBit
{
if (this.RESET.Raised())
{
this.OnLoweringRESET();
LoweringRESET?.Invoke(this, EventArgs.Empty);
this.RESET.Lower();
this.OnLoweredRESET();
LoweredRESET?.Invoke(this, EventArgs.Empty);
}
}
@@ -170,9 +122,9 @@ namespace EightBit
{
if (this.INT.Lowered())
{
this.OnRaisingINT();
RaisingINT?.Invoke(this, EventArgs.Empty);
this.INT.Raise();
this.OnRaisedINT();
RaisedINT?.Invoke(this, EventArgs.Empty);
}
}
@@ -180,9 +132,9 @@ namespace EightBit
{
if (this.INT.Raised())
{
this.OnLoweringINT();
LoweringINT?.Invoke(this, EventArgs.Empty);
this.INT.Lower();
this.OnLoweredINT();
LoweredINT?.Invoke(this, EventArgs.Empty);
}
}
@@ -226,13 +178,11 @@ namespace EightBit
protected void MemoryWrite(Register16 address, byte data)
{
ArgumentNullException.ThrowIfNull(address);
this.MemoryWrite(address.Low, address.High, data);
}
protected void MemoryWrite(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
this.MemoryWrite(address.Low, address.High);
}
@@ -260,7 +210,6 @@ namespace EightBit
protected byte MemoryRead(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
return this.MemoryRead(address.Low, address.High);
}
@@ -286,7 +235,6 @@ namespace EightBit
protected Register16 GetWordPaged(Register16 address)
{
ArgumentNullException.ThrowIfNull(address);
return this.GetWordPaged(address.High, address.Low);
}
@@ -300,7 +248,6 @@ namespace EightBit
protected void SetWordPaged(Register16 address, Register16 value)
{
ArgumentNullException.ThrowIfNull(address);
this.SetWordPaged(address.High, address.Low, value);
}
@@ -354,7 +301,6 @@ namespace EightBit
protected void Jump(Register16 destination)
{
ArgumentNullException.ThrowIfNull(destination);
this.PC.Assign(destination);
}

View File

@@ -46,7 +46,6 @@ namespace EightBit
public Register16(Register16 rhs)
{
ArgumentNullException.ThrowIfNull(rhs);
this.Low = rhs.Low;
this.High = rhs.High;
}
@@ -68,7 +67,6 @@ namespace EightBit
public static bool operator ==(Register16 left, Register16 right)
{
ArgumentNullException.ThrowIfNull(left);
return left.Equals(right);
}
@@ -88,7 +86,6 @@ namespace EightBit
public void Assign(Register16 from)
{
ArgumentNullException.ThrowIfNull(from);
this.Assign(from._low, from._high);
}
}

View File

@@ -8,8 +8,14 @@ namespace M6502
{
using EightBit;
public abstract class Core(Bus bus) : LittleEndianProcessor(bus)
public abstract class Core : LittleEndianProcessor
{
protected Core(Bus bus)
: base(bus)
{
this.RaisedPOWER += this.Core_RaisedPOWER;
}
#region Pin controls
#region NMI pin
@@ -104,16 +110,22 @@ namespace M6502
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
protected virtual void RaiseSYNC()
{
this.OnRaisingSYNC();
if (this.SYNC.Lowered())
{
RaisingSYNC?.Invoke(this, EventArgs.Empty);
this.SYNC.Raise();
this.OnRaisedSYNC();
RaisedSYNC?.Invoke(this, EventArgs.Empty);
}
}
protected virtual void LowerSYNC()
{
this.OnLoweringSYNC();
if (this.SYNC.Raised())
{
LoweringSYNC?.Invoke(this, EventArgs.Empty);
this.SYNC.Lower();
this.OnLoweredSYNC();
LoweredSYNC?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -190,7 +202,7 @@ namespace M6502
#endregion
protected override void OnRaisedPOWER()
private void Core_RaisedPOWER(object? sender, EventArgs e)
{
this.X = (byte)Bits.Bit7;
this.Y = 0;
@@ -199,7 +211,6 @@ namespace M6502
this.S = (byte)Mask.Eight;
this.LowerSYNC();
this.LowerRW();
base.OnRaisedPOWER();
}
#endregion
@@ -551,9 +562,7 @@ namespace M6502
private void FetchInstruction()
{
// Instruction fetch beginning
this.LowerSYNC();
System.Diagnostics.Debug.Assert(this.Cycles == 1, "An extra cycle has occurred");
// Can't use fetchByte, since that would add an extra tick.
@@ -561,8 +570,6 @@ namespace M6502
this.OpCode = this.ReadFromBus();
System.Diagnostics.Debug.Assert(this.Cycles == 1, "BUS read has introduced stray cycles");
// Instruction fetch has now completed
this.RaiseSYNC();
}

View File

@@ -282,13 +282,9 @@
}
}
private void Runner_ReadByte(object? sender, EventArgs e) => this.AddActualReadCycle(this.Runner.Address, this.Runner.Data);
private void Runner_ReadByte(object? sender, EventArgs e) => this.AddActualCycle(this.Runner.Address, this.Runner.Data, "read");
private void Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualWriteCycle(this.Runner.Address, this.Runner.Data);
private void AddActualReadCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "read");
private void AddActualWriteCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "write");
private void Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualCycle(this.Runner.Address, this.Runner.Data, "write");
private void AddActualCycle(EightBit.Register16 address, byte value, string action) => this.AddActualCycle(address.Word, value, action);

View File

@@ -98,21 +98,30 @@ namespace Z80.FuseTest
public override void Initialize()
{
this.ReadByte += this.Event_ReadByte;
this.WrittenByte += this.Event_WrittenByte;
this.ports.ReadPort += this.Ports_ReadPort;
this.ports.WrittenPort += this.Ports_WrittenPort;
this.cpu.ExecutedInstruction += this.Cpu_ExecutedInstruction;
}
protected override void OnReadByte()
{
this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "MR", this.Address.Word, this.Data));
base.OnReadByte();
}
private void Ports_ReadPort(object? sender, EventArgs e) => this.AddActualEvent("PR");
private void Ports_WrittenPort(object? sender, EventArgs e) => this.AddActualEvent("PW");
private void Event_ReadByte(object? sender, EventArgs e) => this.AddActualEvent("MR");
private void Event_WrittenByte(object? sender, EventArgs e) => this.AddActualEvent("MW");
protected override void OnWrittenByte()
private void AddActualEvent(string specifier)
{
this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "MW", this.Address.Word, this.Data));
base.OnWrittenByte();
var address = this.Address.Word;
var cycles = this.totalCycles + this.cpu.Cycles;
if (specifier.EndsWith('C'))
{
this.actualEvents.Add(new TestEvent(cycles, specifier, address));
}
else
{
this.actualEvents.Add(new TestEvent(cycles, specifier, address, this.Data));
}
}
private static void DumpDifference(string description, byte expected, byte actual)
@@ -121,11 +130,12 @@ namespace Z80.FuseTest
Console.Error.WriteLine(output);
}
private void Ports_WrittenPort(object? sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PW", this.Address.Word, this.Data));
private void Ports_ReadPort(object? sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PR", this.Address.Word, this.Data));
private void Cpu_ExecutedInstruction(object? sender, EventArgs e) => this.totalCycles += this.cpu.Cycles;
private void Cpu_ExecutedInstruction(object? sender, EventArgs e)
{
var output = $"**** Cycle count: {this.cpu.Cycles}";
Console.Out.WriteLine(output);
this.totalCycles += this.cpu.Cycles;
}
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
{

View File

@@ -5,12 +5,17 @@
namespace Z80
{
using EightBit;
using System.Diagnostics;
public class Z80(Bus bus, InputOutput ports) : IntelProcessor(bus)
public class Z80 : IntelProcessor
{
private readonly InputOutput _ports = ports;
public Z80(Bus bus, InputOutput ports)
: base(bus)
{
this._ports = ports;
this.RaisedPOWER += this.Z80_RaisedPOWER;
}
private readonly InputOutput _ports;
private readonly Register16[] _accumulatorFlags = [new Register16(), new Register16()];
private readonly Register16[][] _registers =
@@ -161,7 +166,7 @@ namespace Z80
}
}
protected override void OnRaisedPOWER()
private void Z80_RaisedPOWER(object? sender, EventArgs e)
{
this.RaiseM1();
this.RaiseRFSH();
@@ -183,8 +188,6 @@ namespace Z80
base.ResetWorkingRegisters();
this.ResetPrefixes();
base.OnRaisedPOWER();
}
private void ResetPrefixes()
@@ -192,34 +195,7 @@ namespace Z80
this._prefixCB = this._prefixDD = this._prefixED = this._prefixFD = false;
}
private static void WithPinChange(Func<bool> check, Action enter, Action leave, Action task)
{
if (check())
{
enter();
try
{
task();
}
finally
{
leave();
}
}
}
private static byte WithPin(Action enter, Action leave, Func<byte> task)
{
enter();
try
{
return task();
}
finally
{
leave();
}
}
#region Z80 specific pins
#region NMI pin
@@ -235,22 +211,14 @@ namespace Z80
public ref PinLevel NMI => ref this._nmiLine;
protected virtual void OnRaisingNMI() => RaisingNMI?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedNMI() => RaisedNMI?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringNMI() => LoweringNMI?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredNMI() => LoweredNMI?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseNMI()
{
if (this.NMI.Lowered())
{
this.OnRaisingNMI();
RaisingNMI?.Invoke(this, EventArgs.Empty);
this.NMI.Raise();
this.OnRaisedNMI();
RaisedNMI?.Invoke(this, EventArgs.Empty);
}
}
@@ -258,9 +226,9 @@ namespace Z80
{
if (this.NMI.Raised())
{
this.OnLoweringNMI();
LoweringNMI?.Invoke(this, EventArgs.Empty);
this.NMI.Lower();
this.OnLoweredNMI();
LoweredNMI?.Invoke(this, EventArgs.Empty);
}
}
@@ -280,14 +248,6 @@ namespace Z80
public ref PinLevel M1 => ref this._m1Line;
protected virtual void OnRaisingM1() => RaisingM1?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedM1()
{
++this.REFRESH;
RaisedM1?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnLoweringM1() => LoweringM1?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredM1() => LoweredM1?.Invoke(this, EventArgs.Empty);
@@ -295,17 +255,23 @@ namespace Z80
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseM1()
{
WithPinChange(() => this.M1.Lowered(), this.OnRaisingM1, this.OnRaisedM1, () => this.M1.Raise());
if (this.M1.Lowered())
{
RaisingM1?.Invoke(this, EventArgs.Empty);
this.M1.Raise();
++this.REFRESH;
RaisedM1?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerM1()
{
WithPinChange(() => this.M1.Raised(), this.OnLoweringM1, this.OnLoweredM1, () => this.M1.Lower());
}
private byte WithM1(Func<byte> function)
if (this.M1.Raised())
{
return WithPin(this.LowerM1, this.RaiseM1, function);
LoweringM1?.Invoke(this, EventArgs.Empty);
this.M1.Lower();
LoweredM1?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -329,28 +295,25 @@ namespace Z80
public ref PinLevel RFSH => ref this._rfshLine;
protected virtual void OnRaisingRFSH() => RaisingRFSH?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedRFSH() => RaisedRFSH?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringRFSH() => LoweringRFSH?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredRFSH() => LoweredRFSH?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseRFSH()
{
WithPinChange(() => this.RFSH.Lowered(), this.OnRaisingRFSH, this.OnRaisedRFSH, () => this.RFSH.Raise());
if (this.RFSH.Lowered())
{
RaisingRFSH?.Invoke(this, EventArgs.Empty);
this.RFSH.Raise();
RaisedRFSH?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerRFSH()
{
WithPinChange(() => this.RFSH.Raised(), this.OnLoweringRFSH, this.OnLoweredRFSH, () => this.RFSH.Lower());
}
private byte WithRFSH(Func<byte> function)
if (this.RFSH.Raised())
{
return WithPin(this.LowerRFSH, this.RaiseRFSH, function);
LoweringRFSH?.Invoke(this, EventArgs.Empty);
this.RFSH.Lower();
LoweredRFSH?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -369,28 +332,25 @@ namespace Z80
public ref PinLevel MREQ => ref this._mreqLine;
protected virtual void OnLoweringMREQ() => LoweringMREQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredMREQ() => LoweredMREQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingMREQ() => RaisingMREQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedMREQ() => RaisedMREQ?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseMREQ()
{
WithPinChange(() => this.MREQ.Lowered(), this.OnRaisingMREQ, this.OnRaisedMREQ, () => this.MREQ.Raise());
if (this.MREQ.Lowered())
{
RaisingMREQ?.Invoke(this, EventArgs.Empty);
this.MREQ.Raise();
RaisedMREQ?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerMREQ()
{
WithPinChange(() => this.MREQ.Raised(), this.OnLoweringMREQ, this.OnLoweredMREQ, () => this.MREQ.Lower());
}
private byte WithMREQ(Func<byte> function)
if (this.MREQ.Raised())
{
return WithPin(this.LowerMREQ, this.RaiseMREQ, function);
LoweringMREQ?.Invoke(this, EventArgs.Empty);
this.MREQ.Lower();
LoweredMREQ?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -409,29 +369,25 @@ namespace Z80
public ref PinLevel IORQ => ref this._iorqLine;
protected virtual void OnLoweringIORQ() => LoweringIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredIORQ() => LoweredIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingIORQ() => RaisingIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedIORQ() => RaisedIORQ?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseIORQ()
{
WithPinChange(() => this.IORQ.Lowered(), this.OnRaisingIORQ, this.OnRaisedIORQ, () => this.IORQ.Raise());
if (this.IORQ.Lowered())
{
RaisingIORQ?.Invoke(this, EventArgs.Empty);
this.IORQ.Raise();
RaisedIORQ?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerIORQ()
{
WithPinChange(() => this.IORQ.Raised(), this.OnLoweringIORQ, this.OnLoweredIORQ, () => this.IORQ.Lower());
}
private byte WithIORQ(Func<byte> function)
if (this.IORQ.Raised())
{
return WithPin(this.LowerIORQ, this.RaiseIORQ, function);
LoweringIORQ?.Invoke(this, EventArgs.Empty);
this.IORQ.Lower();
LoweredIORQ?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -450,28 +406,25 @@ namespace Z80
public ref PinLevel RD => ref this._rdLine;
protected virtual void OnLoweringRD() => LoweringRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredRD() => LoweredRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingRD() => RaisingRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedRD() => RaisedRD?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseRD()
{
WithPinChange(() => this.RD.Lowered(), this.OnRaisingRD, this.OnRaisedRD, () => this.RD.Raise());
if (this.RD.Lowered())
{
RaisingRD?.Invoke(this, EventArgs.Empty);
this.RD.Raise();
RaisedRD?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerRD()
{
WithPinChange(() => this.RD.Raised(), this.OnLoweringRD, this.OnLoweredRD, () => this.RD.Lower());
}
private byte WithRD(Func<byte> function)
if (this.RD.Raised())
{
return WithPin(this.LowerRD, this.RaiseRD, function);
LoweringRD?.Invoke(this, EventArgs.Empty);
this.RD.Lower();
LoweredRD?.Invoke(this, EventArgs.Empty);
}
}
#endregion
@@ -490,63 +443,50 @@ namespace Z80
public ref PinLevel WR => ref this._wrLine;
protected virtual void OnLoweringWR() => LoweringWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredWR() => LoweredWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingWR() => RaisingWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedWR() => RaisedWR?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public virtual void RaiseWR()
{
WithPinChange(() => this.WR.Lowered(), this.OnRaisingWR, this.OnRaisedWR, () => this.WR.Raise());
if (this.WR.Lowered())
{
RaisingWR?.Invoke(this, EventArgs.Empty);
this.WR.Raise();
RaisedWR?.Invoke(this, EventArgs.Empty);
}
}
public virtual void LowerWR()
{
WithPinChange(() => this.WR.Raised(), this.OnLoweringWR, this.OnLoweredWR, () => this.WR.Lower());
}
private byte WithWR(Func<byte> function)
if (this.WR.Raised())
{
this.LowerWR();
try
{
return function();
}
finally
{
this.RaiseWR();
LoweringWR?.Invoke(this, EventArgs.Empty);
this.WR.Lower();
LoweredWR?.Invoke(this, EventArgs.Empty);
}
}
#endregion
#endregion
protected override void MemoryWrite()
{
_ = this.WithMREQ(() =>
{
return this.WithWR(() =>
{
this.LowerMREQ();
this.LowerWR();
this.Tick(3);
base.MemoryWrite();
return 0;
});
});
this.RaiseWR();
this.RaiseMREQ();
}
protected override byte MemoryRead()
{
return this.WithMREQ(() =>
{
return this.WithRD(() =>
{
this.LowerMREQ();
this.LowerRD();
this.Tick(3);
return base.MemoryRead();
});
});
var returned = base.MemoryRead();
this.RaiseRD();
this.RaiseMREQ();
return returned;
}
protected override void HandleRESET()
@@ -562,13 +502,11 @@ namespace Z80
{
base.HandleINT();
var data = this.WithM1(() =>
{
return this.WithIORQ(() =>
{
return this.Bus.Data;
});
});
this.LowerM1();
this.LowerIORQ();
var data = this.Bus.Data;
this.RaiseIORQ();
this.RaiseM1();
this.DisableInterrupts();
this.Tick(5);
@@ -1723,18 +1661,17 @@ namespace Z80
private byte ReadInitialOpCode()
{
this.Tick();
var returned = this.WithM1(() =>
{
return this.MemoryRead(this.PC);
});
this.LowerM1();
var returned = this.MemoryRead(this.PC);
this.RaiseM1();
this.Bus.Address.Assign(this.REFRESH, this.IV);
_ = this.WithRFSH(() =>
{
return this.WithMREQ(() =>
{
return 0;
});
});
this.LowerRFSH();
this.LowerMREQ();
this.RaiseMREQ();
this.RaiseRFSH();
return returned;
}