mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-06-27 14:24:41 +00:00
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:
@ -14,7 +14,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public override void PokeWord(ushort address, Register16 value)
|
public override void PokeWord(ushort address, Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.Bus.Poke(address, value.High);
|
this.Bus.Poke(address, value.High);
|
||||||
this.Bus.Poke(++address, value.Low);
|
this.Bus.Poke(++address, value.Low);
|
||||||
}
|
}
|
||||||
@ -51,14 +50,12 @@ namespace EightBit
|
|||||||
|
|
||||||
protected override void PushWord(Register16 value)
|
protected override void PushWord(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.Push(value.Low);
|
this.Push(value.Low);
|
||||||
this.Push(value.High);
|
this.Push(value.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetWord(Register16 value)
|
protected override void SetWord(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.MemoryWrite(value.High);
|
this.MemoryWrite(value.High);
|
||||||
++this.Bus.Address.Word;
|
++this.Bus.Address.Word;
|
||||||
this.MemoryWrite(value.Low);
|
this.MemoryWrite(value.Low);
|
||||||
@ -66,7 +63,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected override void SetWordPaged(Register16 value)
|
protected override void SetWordPaged(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.MemoryWrite(value.High);
|
this.MemoryWrite(value.High);
|
||||||
++this.Bus.Address.Low;
|
++this.Bus.Address.Low;
|
||||||
this.MemoryWrite(value.Low);
|
this.MemoryWrite(value.Low);
|
||||||
|
@ -28,7 +28,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public byte Peek(Register16 absolute)
|
public byte Peek(Register16 absolute)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(absolute);
|
|
||||||
return this.Peek(absolute.Word);
|
return this.Peek(absolute.Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public void Poke(Register16 absolute, byte value)
|
public void Poke(Register16 absolute, byte value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(absolute);
|
|
||||||
this.Poke(absolute.Word, value);
|
this.Poke(absolute.Word, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +56,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public byte Read(Register16 absolute)
|
public byte Read(Register16 absolute)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(absolute);
|
|
||||||
return this.Read(absolute.Low, absolute.High);
|
return this.Read(absolute.Low, absolute.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +86,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public void Write(Register16 absolute, byte value)
|
public void Write(Register16 absolute, byte value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(absolute);
|
|
||||||
this.Write(absolute.Low, absolute.High, value);
|
this.Write(absolute.Low, absolute.High, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +129,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected ref byte Reference(Register16 absolute)
|
protected ref byte Reference(Register16 absolute)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(absolute);
|
|
||||||
return ref this.Reference(absolute.Word);
|
return ref this.Reference(absolute.Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.POWER.Lowered())
|
if (this.POWER.Lowered())
|
||||||
{
|
{
|
||||||
this.OnRaisingPOWER();
|
RaisingPOWER?.Invoke(this, EventArgs.Empty);
|
||||||
this.POWER.Raise();
|
this.POWER.Raise();
|
||||||
this.OnRaisedPOWER();
|
RaisedPOWER?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,18 +35,10 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.POWER.Raised())
|
if (this.POWER.Raised())
|
||||||
{
|
{
|
||||||
this.OnLoweringPOWER();
|
LoweringPOWER?.Invoke(this, EventArgs.Empty);
|
||||||
this.POWER.Lower();
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||||
<SignAssembly>False</SignAssembly>
|
<SignAssembly>False</SignAssembly>
|
||||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||||
<AnalysisLevel>latest-all</AnalysisLevel>
|
<AnalysisLevel>latest-recommended</AnalysisLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@ -20,6 +20,7 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
this._decodedOpCodes[i] = new((byte)i);
|
this._decodedOpCodes[i] = new((byte)i);
|
||||||
}
|
}
|
||||||
|
this.RaisedPOWER += this.IntelProcessor_RaisedPOWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<EventArgs>? RaisingHALT;
|
public event EventHandler<EventArgs>? RaisingHALT;
|
||||||
@ -67,9 +68,10 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.HALT.Lowered())
|
if (this.HALT.Lowered())
|
||||||
{
|
{
|
||||||
this.OnRaisingHALT();
|
RaisingHALT?.Invoke(this, EventArgs.Empty);
|
||||||
this.HALT.Raise();
|
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())
|
if (this.HALT.Raised())
|
||||||
{
|
{
|
||||||
this.OnLoweringHALT();
|
LoweringHALT?.Invoke(this, EventArgs.Empty);
|
||||||
this.HALT.Lower();
|
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];
|
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.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Sixteen;
|
||||||
this.RaiseHALT();
|
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()
|
protected override void HandleRESET()
|
||||||
|
@ -15,7 +15,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public override void PokeWord(ushort address, Register16 value)
|
public override void PokeWord(ushort address, Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.Bus.Poke(address, value.Low);
|
this.Bus.Poke(address, value.Low);
|
||||||
this.Bus.Poke(++address, value.High);
|
this.Bus.Poke(++address, value.High);
|
||||||
}
|
}
|
||||||
@ -52,14 +51,12 @@ namespace EightBit
|
|||||||
|
|
||||||
protected override void PushWord(Register16 value)
|
protected override void PushWord(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.Push(value.High);
|
this.Push(value.High);
|
||||||
this.Push(value.Low);
|
this.Push(value.Low);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetWord(Register16 value)
|
protected override void SetWord(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.MemoryWrite(value.Low);
|
this.MemoryWrite(value.Low);
|
||||||
++this.Bus.Address.Word;
|
++this.Bus.Address.Word;
|
||||||
this.MemoryWrite(value.High);
|
this.MemoryWrite(value.High);
|
||||||
@ -67,7 +64,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected override void SetWordPaged(Register16 value)
|
protected override void SetWordPaged(Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
|
||||||
this.MemoryWrite(value.Low);
|
this.MemoryWrite(value.Low);
|
||||||
++this.Bus.Address.Low;
|
++this.Bus.Address.Low;
|
||||||
this.MemoryWrite(value.High);
|
this.MemoryWrite(value.High);
|
||||||
|
@ -10,57 +10,9 @@ namespace EightBit
|
|||||||
|
|
||||||
public event EventHandler<EventArgs>? ExecutingInstruction;
|
public event EventHandler<EventArgs>? ExecutingInstruction;
|
||||||
public event EventHandler<EventArgs>? ExecutedInstruction;
|
public event EventHandler<EventArgs>? ExecutedInstruction;
|
||||||
protected virtual void OnExecutedInstruction() => ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
|
||||||
protected virtual void OnExecutingInstruction() => ExecutingInstruction?.Invoke(this, EventArgs.Empty);
|
|
||||||
|
|
||||||
#endregion
|
#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 _resetLine;
|
||||||
private PinLevel _intLine;
|
private PinLevel _intLine;
|
||||||
@ -108,12 +60,12 @@ namespace EightBit
|
|||||||
public virtual int Step()
|
public virtual int Step()
|
||||||
{
|
{
|
||||||
this.ResetCycles();
|
this.ResetCycles();
|
||||||
this.OnExecutingInstruction();
|
ExecutingInstruction?.Invoke(this, EventArgs.Empty);
|
||||||
if (this.Powered)
|
if (this.Powered)
|
||||||
{
|
{
|
||||||
this.PoweredStep();
|
this.PoweredStep();
|
||||||
}
|
}
|
||||||
this.OnExecutedInstruction();
|
ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
||||||
return this.Cycles;
|
return this.Cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,9 +101,9 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.RESET.Lowered())
|
if (this.RESET.Lowered())
|
||||||
{
|
{
|
||||||
this.OnRaisingRESET();
|
RaisingRESET?.Invoke(this, EventArgs.Empty);
|
||||||
this.RESET.Raise();
|
this.RESET.Raise();
|
||||||
this.OnRaisedRESET();
|
RaisedRESET?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,9 +111,9 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.RESET.Raised())
|
if (this.RESET.Raised())
|
||||||
{
|
{
|
||||||
this.OnLoweringRESET();
|
LoweringRESET?.Invoke(this, EventArgs.Empty);
|
||||||
this.RESET.Lower();
|
this.RESET.Lower();
|
||||||
this.OnLoweredRESET();
|
LoweredRESET?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,9 +122,9 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.INT.Lowered())
|
if (this.INT.Lowered())
|
||||||
{
|
{
|
||||||
this.OnRaisingINT();
|
RaisingINT?.Invoke(this, EventArgs.Empty);
|
||||||
this.INT.Raise();
|
this.INT.Raise();
|
||||||
this.OnRaisedINT();
|
RaisedINT?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,9 +132,9 @@ namespace EightBit
|
|||||||
{
|
{
|
||||||
if (this.INT.Raised())
|
if (this.INT.Raised())
|
||||||
{
|
{
|
||||||
this.OnLoweringINT();
|
LoweringINT?.Invoke(this, EventArgs.Empty);
|
||||||
this.INT.Lower();
|
this.INT.Lower();
|
||||||
this.OnLoweredINT();
|
LoweredINT?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,13 +178,11 @@ namespace EightBit
|
|||||||
|
|
||||||
protected void MemoryWrite(Register16 address, byte data)
|
protected void MemoryWrite(Register16 address, byte data)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(address);
|
|
||||||
this.MemoryWrite(address.Low, address.High, data);
|
this.MemoryWrite(address.Low, address.High, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void MemoryWrite(Register16 address)
|
protected void MemoryWrite(Register16 address)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(address);
|
|
||||||
this.MemoryWrite(address.Low, address.High);
|
this.MemoryWrite(address.Low, address.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +210,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected byte MemoryRead(Register16 address)
|
protected byte MemoryRead(Register16 address)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(address);
|
|
||||||
return this.MemoryRead(address.Low, address.High);
|
return this.MemoryRead(address.Low, address.High);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +235,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected Register16 GetWordPaged(Register16 address)
|
protected Register16 GetWordPaged(Register16 address)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(address);
|
|
||||||
return this.GetWordPaged(address.High, address.Low);
|
return this.GetWordPaged(address.High, address.Low);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +248,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected void SetWordPaged(Register16 address, Register16 value)
|
protected void SetWordPaged(Register16 address, Register16 value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(address);
|
|
||||||
this.SetWordPaged(address.High, address.Low, value);
|
this.SetWordPaged(address.High, address.Low, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +301,6 @@ namespace EightBit
|
|||||||
|
|
||||||
protected void Jump(Register16 destination)
|
protected void Jump(Register16 destination)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(destination);
|
|
||||||
this.PC.Assign(destination);
|
this.PC.Assign(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public Register16(Register16 rhs)
|
public Register16(Register16 rhs)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(rhs);
|
|
||||||
this.Low = rhs.Low;
|
this.Low = rhs.Low;
|
||||||
this.High = rhs.High;
|
this.High = rhs.High;
|
||||||
}
|
}
|
||||||
@ -68,7 +67,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public static bool operator ==(Register16 left, Register16 right)
|
public static bool operator ==(Register16 left, Register16 right)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(left);
|
|
||||||
return left.Equals(right);
|
return left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +86,6 @@ namespace EightBit
|
|||||||
|
|
||||||
public void Assign(Register16 from)
|
public void Assign(Register16 from)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(from);
|
|
||||||
this.Assign(from._low, from._high);
|
this.Assign(from._low, from._high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,14 @@ namespace M6502
|
|||||||
{
|
{
|
||||||
using EightBit;
|
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 Pin controls
|
||||||
|
|
||||||
#region NMI pin
|
#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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
protected virtual void RaiseSYNC()
|
protected virtual void RaiseSYNC()
|
||||||
{
|
{
|
||||||
this.OnRaisingSYNC();
|
if (this.SYNC.Lowered())
|
||||||
this.SYNC.Raise();
|
{
|
||||||
this.OnRaisedSYNC();
|
RaisingSYNC?.Invoke(this, EventArgs.Empty);
|
||||||
|
this.SYNC.Raise();
|
||||||
|
RaisedSYNC?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void LowerSYNC()
|
protected virtual void LowerSYNC()
|
||||||
{
|
{
|
||||||
this.OnLoweringSYNC();
|
if (this.SYNC.Raised())
|
||||||
this.SYNC.Lower();
|
{
|
||||||
this.OnLoweredSYNC();
|
LoweringSYNC?.Invoke(this, EventArgs.Empty);
|
||||||
|
this.SYNC.Lower();
|
||||||
|
LoweredSYNC?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -190,7 +202,7 @@ namespace M6502
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected override void OnRaisedPOWER()
|
private void Core_RaisedPOWER(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
this.X = (byte)Bits.Bit7;
|
this.X = (byte)Bits.Bit7;
|
||||||
this.Y = 0;
|
this.Y = 0;
|
||||||
@ -199,7 +211,6 @@ namespace M6502
|
|||||||
this.S = (byte)Mask.Eight;
|
this.S = (byte)Mask.Eight;
|
||||||
this.LowerSYNC();
|
this.LowerSYNC();
|
||||||
this.LowerRW();
|
this.LowerRW();
|
||||||
base.OnRaisedPOWER();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -551,9 +562,7 @@ namespace M6502
|
|||||||
|
|
||||||
private void FetchInstruction()
|
private void FetchInstruction()
|
||||||
{
|
{
|
||||||
// Instruction fetch beginning
|
|
||||||
this.LowerSYNC();
|
this.LowerSYNC();
|
||||||
|
|
||||||
System.Diagnostics.Debug.Assert(this.Cycles == 1, "An extra cycle has occurred");
|
System.Diagnostics.Debug.Assert(this.Cycles == 1, "An extra cycle has occurred");
|
||||||
|
|
||||||
// Can't use fetchByte, since that would add an extra tick.
|
// Can't use fetchByte, since that would add an extra tick.
|
||||||
@ -561,8 +570,6 @@ namespace M6502
|
|||||||
this.OpCode = this.ReadFromBus();
|
this.OpCode = this.ReadFromBus();
|
||||||
|
|
||||||
System.Diagnostics.Debug.Assert(this.Cycles == 1, "BUS read has introduced stray cycles");
|
System.Diagnostics.Debug.Assert(this.Cycles == 1, "BUS read has introduced stray cycles");
|
||||||
|
|
||||||
// Instruction fetch has now completed
|
|
||||||
this.RaiseSYNC();
|
this.RaiseSYNC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualCycle(this.Runner.Address, this.Runner.Data, "write");
|
||||||
|
|
||||||
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 AddActualCycle(EightBit.Register16 address, byte value, string action) => this.AddActualCycle(address.Word, value, action);
|
private void AddActualCycle(EightBit.Register16 address, byte value, string action) => this.AddActualCycle(address.Word, value, action);
|
||||||
|
|
||||||
|
@ -98,21 +98,30 @@ namespace Z80.FuseTest
|
|||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
this.ReadByte += this.Event_ReadByte;
|
||||||
|
this.WrittenByte += this.Event_WrittenByte;
|
||||||
this.ports.ReadPort += this.Ports_ReadPort;
|
this.ports.ReadPort += this.Ports_ReadPort;
|
||||||
this.ports.WrittenPort += this.Ports_WrittenPort;
|
this.ports.WrittenPort += this.Ports_WrittenPort;
|
||||||
this.cpu.ExecutedInstruction += this.Cpu_ExecutedInstruction;
|
this.cpu.ExecutedInstruction += this.Cpu_ExecutedInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnReadByte()
|
private void Ports_ReadPort(object? sender, EventArgs e) => this.AddActualEvent("PR");
|
||||||
{
|
private void Ports_WrittenPort(object? sender, EventArgs e) => this.AddActualEvent("PW");
|
||||||
this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "MR", this.Address.Word, this.Data));
|
private void Event_ReadByte(object? sender, EventArgs e) => this.AddActualEvent("MR");
|
||||||
base.OnReadByte();
|
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));
|
var address = this.Address.Word;
|
||||||
base.OnWrittenByte();
|
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)
|
private static void DumpDifference(string description, byte expected, byte actual)
|
||||||
@ -121,11 +130,12 @@ namespace Z80.FuseTest
|
|||||||
Console.Error.WriteLine(output);
|
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 Cpu_ExecutedInstruction(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
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));
|
var output = $"**** Cycle count: {this.cpu.Cycles}";
|
||||||
|
Console.Out.WriteLine(output);
|
||||||
private void Cpu_ExecutedInstruction(object? sender, EventArgs e) => this.totalCycles += this.cpu.Cycles;
|
this.totalCycles += this.cpu.Cycles;
|
||||||
|
}
|
||||||
|
|
||||||
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
||||||
{
|
{
|
||||||
|
295
Z80/Z80.cs
295
Z80/Z80.cs
@ -5,12 +5,17 @@
|
|||||||
namespace Z80
|
namespace Z80
|
||||||
{
|
{
|
||||||
using EightBit;
|
using EightBit;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
|
public class Z80 : IntelProcessor
|
||||||
public class Z80(Bus bus, InputOutput ports) : IntelProcessor(bus)
|
|
||||||
{
|
{
|
||||||
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[] _accumulatorFlags = [new Register16(), new Register16()];
|
||||||
private readonly Register16[][] _registers =
|
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.RaiseM1();
|
||||||
this.RaiseRFSH();
|
this.RaiseRFSH();
|
||||||
@ -183,8 +188,6 @@ namespace Z80
|
|||||||
base.ResetWorkingRegisters();
|
base.ResetWorkingRegisters();
|
||||||
|
|
||||||
this.ResetPrefixes();
|
this.ResetPrefixes();
|
||||||
|
|
||||||
base.OnRaisedPOWER();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetPrefixes()
|
private void ResetPrefixes()
|
||||||
@ -192,34 +195,7 @@ namespace Z80
|
|||||||
this._prefixCB = this._prefixDD = this._prefixED = this._prefixFD = false;
|
this._prefixCB = this._prefixDD = this._prefixED = this._prefixFD = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WithPinChange(Func<bool> check, Action enter, Action leave, Action task)
|
#region Z80 specific pins
|
||||||
{
|
|
||||||
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 NMI pin
|
#region NMI pin
|
||||||
|
|
||||||
@ -235,22 +211,14 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel NMI => ref this._nmiLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseNMI()
|
public virtual void RaiseNMI()
|
||||||
{
|
{
|
||||||
if (this.NMI.Lowered())
|
if (this.NMI.Lowered())
|
||||||
{
|
{
|
||||||
this.OnRaisingNMI();
|
RaisingNMI?.Invoke(this, EventArgs.Empty);
|
||||||
this.NMI.Raise();
|
this.NMI.Raise();
|
||||||
this.OnRaisedNMI();
|
RaisedNMI?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,9 +226,9 @@ namespace Z80
|
|||||||
{
|
{
|
||||||
if (this.NMI.Raised())
|
if (this.NMI.Raised())
|
||||||
{
|
{
|
||||||
this.OnLoweringNMI();
|
LoweringNMI?.Invoke(this, EventArgs.Empty);
|
||||||
this.NMI.Lower();
|
this.NMI.Lower();
|
||||||
this.OnLoweredNMI();
|
LoweredNMI?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,14 +248,6 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel M1 => ref this._m1Line;
|
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 OnLoweringM1() => LoweringM1?.Invoke(this, EventArgs.Empty);
|
||||||
|
|
||||||
protected virtual void OnLoweredM1() => LoweredM1?.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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseM1()
|
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()
|
public virtual void LowerM1()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.M1.Raised(), this.OnLoweringM1, this.OnLoweredM1, () => this.M1.Lower());
|
if (this.M1.Raised())
|
||||||
}
|
{
|
||||||
|
LoweringM1?.Invoke(this, EventArgs.Empty);
|
||||||
private byte WithM1(Func<byte> function)
|
this.M1.Lower();
|
||||||
{
|
LoweredM1?.Invoke(this, EventArgs.Empty);
|
||||||
return WithPin(this.LowerM1, this.RaiseM1, function);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -329,28 +295,25 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel RFSH => ref this._rfshLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseRFSH()
|
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()
|
public virtual void LowerRFSH()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.RFSH.Raised(), this.OnLoweringRFSH, this.OnLoweredRFSH, () => this.RFSH.Lower());
|
if (this.RFSH.Raised())
|
||||||
}
|
{
|
||||||
|
LoweringRFSH?.Invoke(this, EventArgs.Empty);
|
||||||
private byte WithRFSH(Func<byte> function)
|
this.RFSH.Lower();
|
||||||
{
|
LoweredRFSH?.Invoke(this, EventArgs.Empty);
|
||||||
return WithPin(this.LowerRFSH, this.RaiseRFSH, function);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -369,28 +332,25 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel MREQ => ref this._mreqLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseMREQ()
|
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()
|
public virtual void LowerMREQ()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.MREQ.Raised(), this.OnLoweringMREQ, this.OnLoweredMREQ, () => this.MREQ.Lower());
|
if (this.MREQ.Raised())
|
||||||
}
|
{
|
||||||
|
LoweringMREQ?.Invoke(this, EventArgs.Empty);
|
||||||
private byte WithMREQ(Func<byte> function)
|
this.MREQ.Lower();
|
||||||
{
|
LoweredMREQ?.Invoke(this, EventArgs.Empty);
|
||||||
return WithPin(this.LowerMREQ, this.RaiseMREQ, function);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -409,29 +369,25 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel IORQ => ref this._iorqLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseIORQ()
|
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()
|
public virtual void LowerIORQ()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.IORQ.Raised(), this.OnLoweringIORQ, this.OnLoweredIORQ, () => this.IORQ.Lower());
|
if (this.IORQ.Raised())
|
||||||
}
|
{
|
||||||
|
LoweringIORQ?.Invoke(this, EventArgs.Empty);
|
||||||
private byte WithIORQ(Func<byte> function)
|
this.IORQ.Lower();
|
||||||
{
|
LoweredIORQ?.Invoke(this, EventArgs.Empty);
|
||||||
return WithPin(this.LowerIORQ, this.RaiseIORQ, function);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -450,28 +406,25 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel RD => ref this._rdLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseRD()
|
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()
|
public virtual void LowerRD()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.RD.Raised(), this.OnLoweringRD, this.OnLoweredRD, () => this.RD.Lower());
|
if (this.RD.Raised())
|
||||||
}
|
{
|
||||||
|
LoweringRD?.Invoke(this, EventArgs.Empty);
|
||||||
private byte WithRD(Func<byte> function)
|
this.RD.Lower();
|
||||||
{
|
LoweredRD?.Invoke(this, EventArgs.Empty);
|
||||||
return WithPin(this.LowerRD, this.RaiseRD, function);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -490,63 +443,50 @@ namespace Z80
|
|||||||
|
|
||||||
public ref PinLevel WR => ref this._wrLine;
|
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")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||||
public virtual void RaiseWR()
|
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()
|
public virtual void LowerWR()
|
||||||
{
|
{
|
||||||
WithPinChange(() => this.WR.Raised(), this.OnLoweringWR, this.OnLoweredWR, () => this.WR.Lower());
|
if (this.WR.Raised())
|
||||||
}
|
|
||||||
|
|
||||||
private byte WithWR(Func<byte> function)
|
|
||||||
{
|
|
||||||
this.LowerWR();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return function();
|
LoweringWR?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
this.WR.Lower();
|
||||||
finally
|
LoweredWR?.Invoke(this, EventArgs.Empty);
|
||||||
{
|
|
||||||
this.RaiseWR();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
protected override void MemoryWrite()
|
protected override void MemoryWrite()
|
||||||
{
|
{
|
||||||
_ = this.WithMREQ(() =>
|
this.LowerMREQ();
|
||||||
{
|
this.LowerWR();
|
||||||
return this.WithWR(() =>
|
this.Tick(3);
|
||||||
{
|
base.MemoryWrite();
|
||||||
this.Tick(3);
|
this.RaiseWR();
|
||||||
base.MemoryWrite();
|
this.RaiseMREQ();
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte MemoryRead()
|
protected override byte MemoryRead()
|
||||||
{
|
{
|
||||||
return this.WithMREQ(() =>
|
this.LowerMREQ();
|
||||||
{
|
this.LowerRD();
|
||||||
return this.WithRD(() =>
|
this.Tick(3);
|
||||||
{
|
var returned = base.MemoryRead();
|
||||||
this.Tick(3);
|
this.RaiseRD();
|
||||||
return base.MemoryRead();
|
this.RaiseMREQ();
|
||||||
});
|
return returned;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void HandleRESET()
|
protected override void HandleRESET()
|
||||||
@ -562,13 +502,11 @@ namespace Z80
|
|||||||
{
|
{
|
||||||
base.HandleINT();
|
base.HandleINT();
|
||||||
|
|
||||||
var data = this.WithM1(() =>
|
this.LowerM1();
|
||||||
{
|
this.LowerIORQ();
|
||||||
return this.WithIORQ(() =>
|
var data = this.Bus.Data;
|
||||||
{
|
this.RaiseIORQ();
|
||||||
return this.Bus.Data;
|
this.RaiseM1();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.DisableInterrupts();
|
this.DisableInterrupts();
|
||||||
this.Tick(5);
|
this.Tick(5);
|
||||||
@ -1723,18 +1661,17 @@ namespace Z80
|
|||||||
private byte ReadInitialOpCode()
|
private byte ReadInitialOpCode()
|
||||||
{
|
{
|
||||||
this.Tick();
|
this.Tick();
|
||||||
var returned = this.WithM1(() =>
|
|
||||||
{
|
this.LowerM1();
|
||||||
return this.MemoryRead(this.PC);
|
var returned = this.MemoryRead(this.PC);
|
||||||
});
|
this.RaiseM1();
|
||||||
|
|
||||||
this.Bus.Address.Assign(this.REFRESH, this.IV);
|
this.Bus.Address.Assign(this.REFRESH, this.IV);
|
||||||
_ = this.WithRFSH(() =>
|
this.LowerRFSH();
|
||||||
{
|
this.LowerMREQ();
|
||||||
return this.WithMREQ(() =>
|
this.RaiseMREQ();
|
||||||
{
|
this.RaiseRFSH();
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return returned;
|
return returned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user