mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-04-25 09:16:41 +00:00
Add support for sub-M-cycle accuracy. Not sure how useful this is!
This commit is contained in:
+123
-22
@@ -479,9 +479,16 @@ namespace Z80
|
|||||||
|
|
||||||
private void MemoryUpdate(int ticks)
|
private void MemoryUpdate(int ticks)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(ticks > 0, "Ticks must be greater than zero");
|
||||||
this.OnWritingMemory();
|
this.OnWritingMemory();
|
||||||
|
#if CYCLE_ACCURATE
|
||||||
|
this.Tick(ticks - 1);
|
||||||
|
this.LowerMREQ();
|
||||||
|
this.Tick();
|
||||||
|
#else
|
||||||
this.Tick(ticks);
|
this.Tick(ticks);
|
||||||
this.LowerMREQ();
|
this.LowerMREQ();
|
||||||
|
#endif
|
||||||
this.LowerWR();
|
this.LowerWR();
|
||||||
this.Tick();
|
this.Tick();
|
||||||
base.MemoryWrite();
|
base.MemoryWrite();
|
||||||
@@ -498,30 +505,71 @@ namespace Z80
|
|||||||
|
|
||||||
private void RefreshMemory()
|
private void RefreshMemory()
|
||||||
{
|
{
|
||||||
|
Debug.Assert(this.M1.Lowered(), "M1 must be lowered to refresh memory");
|
||||||
this.Bus.Address.Assign(this.REFRESH, this.IV);
|
this.Bus.Address.Assign(this.REFRESH, this.IV);
|
||||||
this.LowerRFSH();
|
this.LowerRFSH();
|
||||||
|
#if CYCLE_ACCURATE
|
||||||
|
this.LowerMREQ();
|
||||||
|
this.Tick();
|
||||||
|
#else
|
||||||
this.Tick();
|
this.Tick();
|
||||||
this.LowerMREQ();
|
this.LowerMREQ();
|
||||||
|
#endif
|
||||||
this.RaiseMREQ();
|
this.RaiseMREQ();
|
||||||
this.RaiseRFSH();
|
this.RaiseRFSH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetMemoryRead()
|
||||||
|
{
|
||||||
|
this.LowerMREQ();
|
||||||
|
this.LowerRD();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetMemoryRead()
|
||||||
|
{
|
||||||
|
this.RaiseRD();
|
||||||
|
this.RaiseMREQ();
|
||||||
|
}
|
||||||
|
private void MemoryReadWithM1()
|
||||||
|
{
|
||||||
|
Debug.Assert(this.M1.Lowered());
|
||||||
|
this.Tick();
|
||||||
|
this.SetMemoryRead();
|
||||||
|
this.Tick();
|
||||||
|
_ = base.MemoryRead();
|
||||||
|
this.ResetMemoryRead();
|
||||||
|
this.RefreshMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MemoryReadWithoutM1()
|
||||||
|
{
|
||||||
|
Debug.Assert(this.M1.Raised());
|
||||||
|
#if CYCLE_ACCURATE
|
||||||
|
this.SetMemoryRead();
|
||||||
|
_ = base.MemoryRead();
|
||||||
|
this.Tick(2);
|
||||||
|
#else
|
||||||
|
this.Tick();
|
||||||
|
this.SetMemoryRead();
|
||||||
|
this.Tick();
|
||||||
|
_ = base.MemoryRead();
|
||||||
|
#endif
|
||||||
|
this.ResetMemoryRead();
|
||||||
|
}
|
||||||
|
|
||||||
protected override byte MemoryRead()
|
protected override byte MemoryRead()
|
||||||
{
|
{
|
||||||
this.OnReadingMemory();
|
this.OnReadingMemory();
|
||||||
this.Tick();
|
|
||||||
this.LowerMREQ();
|
|
||||||
this.LowerRD();
|
|
||||||
this.Tick();
|
|
||||||
_ = base.MemoryRead();
|
|
||||||
this.RaiseRD();
|
|
||||||
this.RaiseMREQ();
|
|
||||||
if (this.M1.Lowered())
|
if (this.M1.Lowered())
|
||||||
{
|
{
|
||||||
this.RefreshMemory();
|
this.MemoryReadWithM1();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.MemoryReadWithoutM1();
|
||||||
}
|
}
|
||||||
this.Tick();
|
|
||||||
this.OnReadMemory();
|
this.OnReadMemory();
|
||||||
|
this.Tick();
|
||||||
return this.Bus.Data;
|
return this.Bus.Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1472,7 +1520,22 @@ namespace Z80
|
|||||||
if (this._displaced)
|
if (this._displaced)
|
||||||
{
|
{
|
||||||
this.FetchDisplacement();
|
this.FetchDisplacement();
|
||||||
this.Execute(this.FetchByte());
|
{
|
||||||
|
this.ImmediateAddress();
|
||||||
|
#if CYCLE_ACCURATE
|
||||||
|
this.OnReadingMemory();
|
||||||
|
this.Tick();
|
||||||
|
this.SetMemoryRead();
|
||||||
|
var instruction = base.MemoryRead();
|
||||||
|
this.Tick();
|
||||||
|
this.ResetMemoryRead();
|
||||||
|
this.Tick();
|
||||||
|
this.OnReadMemory();
|
||||||
|
#else
|
||||||
|
var instruction = this.MemoryRead();
|
||||||
|
#endif
|
||||||
|
this.Execute(instruction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1604,7 +1667,11 @@ namespace Z80
|
|||||||
this.Restart(0x66);
|
this.Restart(0x66);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FetchDisplacement() => this._displacement = (sbyte)this.FetchByte();
|
private void FetchDisplacement()
|
||||||
|
{
|
||||||
|
Debug.Assert(this.M1.Raised(), "Displacement cannot be fetched during an M1 cycle");
|
||||||
|
this._displacement = (sbyte)this.FetchByte();
|
||||||
|
}
|
||||||
|
|
||||||
// ** From the Z80 CPU User Manual
|
// ** From the Z80 CPU User Manual
|
||||||
// Figure 5 depicts the timing during an M1 (op code fetch) cycle. The Program Counter is
|
// Figure 5 depicts the timing during an M1 (op code fetch) cycle. The Program Counter is
|
||||||
@@ -2341,16 +2408,32 @@ namespace Z80
|
|||||||
this.WritePort();
|
this.WritePort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetIOWrite()
|
||||||
|
{
|
||||||
|
this.LowerIORQ();
|
||||||
|
this.LowerWR();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetIOWrite()
|
||||||
|
{
|
||||||
|
this.RaiseWR();
|
||||||
|
this.RaiseIORQ();
|
||||||
|
}
|
||||||
|
|
||||||
private void WritePort()
|
private void WritePort()
|
||||||
{
|
{
|
||||||
this.MEMPTR.Assign(this.Bus.Address);
|
this.MEMPTR.Assign(this.Bus.Address);
|
||||||
this.Tick(2);
|
this.Tick();
|
||||||
this.LowerIORQ();
|
#if CYCLE_ACCURATE
|
||||||
this.LowerWR();
|
this.SetIOWrite();
|
||||||
|
this.Tick();
|
||||||
|
#else
|
||||||
|
this.Tick();
|
||||||
|
this.SetIOWrite();
|
||||||
|
#endif
|
||||||
this.Tick();
|
this.Tick();
|
||||||
this.Ports.Write(this.Bus.Address, this.Bus.Data);
|
this.Ports.Write(this.Bus.Address, this.Bus.Data);
|
||||||
this.RaiseWR();
|
this.ResetIOWrite();
|
||||||
this.RaiseIORQ();
|
|
||||||
this.Tick();
|
this.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2367,19 +2450,37 @@ namespace Z80
|
|||||||
this.ReadPort();
|
this.ReadPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetIORead()
|
||||||
|
{
|
||||||
|
this.LowerIORQ();
|
||||||
|
this.LowerRD();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetIORead()
|
||||||
|
{
|
||||||
|
this.RaiseRD();
|
||||||
|
this.RaiseIORQ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void ReadPort()
|
private void ReadPort()
|
||||||
{
|
{
|
||||||
this.MEMPTR.Assign(this.Bus.Address);
|
this.MEMPTR.Assign(this.Bus.Address);
|
||||||
this.Tick(2);
|
this.Tick();
|
||||||
this.LowerIORQ();
|
#if CYCLE_ACCURATE
|
||||||
this.LowerRD();
|
this.SetIORead();
|
||||||
this.Bus.Data = this.Ports.Read(this.Bus.Address);
|
this.Bus.Data = this.Ports.Read(this.Bus.Address);
|
||||||
this.Tick();
|
this.Tick();
|
||||||
this.RaiseRD();
|
#else
|
||||||
this.RaiseIORQ();
|
this.Tick();
|
||||||
|
this.SetIORead();
|
||||||
|
this.Bus.Data = this.Ports.Read(this.Bus.Address);
|
||||||
|
#endif
|
||||||
|
this.Tick();
|
||||||
|
this.ResetIORead();
|
||||||
this.Tick();
|
this.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user