Skip to content

Commit 2e1573b

Browse files
committed
Add support for sub-M-cycle accuracy. Not sure how useful this is!
1 parent 072e38f commit 2e1573b

1 file changed

Lines changed: 121 additions & 20 deletions

File tree

Z80/Z80.cs

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,16 @@ public void LowerWR()
479479

480480
private void MemoryUpdate(int ticks)
481481
{
482+
Debug.Assert(ticks > 0, "Ticks must be greater than zero");
482483
this.OnWritingMemory();
484+
#if CYCLE_ACCURATE
485+
this.Tick(ticks - 1);
486+
this.LowerMREQ();
487+
this.Tick();
488+
#else
483489
this.Tick(ticks);
484490
this.LowerMREQ();
491+
#endif
485492
this.LowerWR();
486493
this.Tick();
487494
base.MemoryWrite();
@@ -498,30 +505,71 @@ protected override void MemoryWrite()
498505

499506
private void RefreshMemory()
500507
{
508+
Debug.Assert(this.M1.Lowered(), "M1 must be lowered to refresh memory");
501509
this.Bus.Address.Assign(this.REFRESH, this.IV);
502510
this.LowerRFSH();
511+
#if CYCLE_ACCURATE
512+
this.LowerMREQ();
513+
this.Tick();
514+
#else
503515
this.Tick();
504516
this.LowerMREQ();
517+
#endif
505518
this.RaiseMREQ();
506519
this.RaiseRFSH();
507520
}
508521

509-
protected override byte MemoryRead()
522+
private void SetMemoryRead()
510523
{
511-
this.OnReadingMemory();
512-
this.Tick();
513524
this.LowerMREQ();
514525
this.LowerRD();
515-
this.Tick();
516-
_ = base.MemoryRead();
526+
}
527+
528+
private void ResetMemoryRead()
529+
{
517530
this.RaiseRD();
518531
this.RaiseMREQ();
532+
}
533+
private void MemoryReadWithM1()
534+
{
535+
Debug.Assert(this.M1.Lowered());
536+
this.Tick();
537+
this.SetMemoryRead();
538+
this.Tick();
539+
_ = base.MemoryRead();
540+
this.ResetMemoryRead();
541+
this.RefreshMemory();
542+
}
543+
544+
private void MemoryReadWithoutM1()
545+
{
546+
Debug.Assert(this.M1.Raised());
547+
#if CYCLE_ACCURATE
548+
this.SetMemoryRead();
549+
_ = base.MemoryRead();
550+
this.Tick(2);
551+
#else
552+
this.Tick();
553+
this.SetMemoryRead();
554+
this.Tick();
555+
_ = base.MemoryRead();
556+
#endif
557+
this.ResetMemoryRead();
558+
}
559+
560+
protected override byte MemoryRead()
561+
{
562+
this.OnReadingMemory();
519563
if (this.M1.Lowered())
520564
{
521-
this.RefreshMemory();
565+
this.MemoryReadWithM1();
566+
}
567+
else
568+
{
569+
this.MemoryReadWithoutM1();
522570
}
523-
this.Tick();
524571
this.OnReadMemory();
572+
this.Tick();
525573
return this.Bus.Data;
526574
}
527575

@@ -1472,7 +1520,22 @@ private void ExecuteOther(int x, int y, int z, int p, int q)
14721520
if (this._displaced)
14731521
{
14741522
this.FetchDisplacement();
1475-
this.Execute(this.FetchByte());
1523+
{
1524+
this.ImmediateAddress();
1525+
#if CYCLE_ACCURATE
1526+
this.OnReadingMemory();
1527+
this.Tick();
1528+
this.SetMemoryRead();
1529+
var instruction = base.MemoryRead();
1530+
this.Tick();
1531+
this.ResetMemoryRead();
1532+
this.Tick();
1533+
this.OnReadMemory();
1534+
#else
1535+
var instruction = this.MemoryRead();
1536+
#endif
1537+
this.Execute(instruction);
1538+
}
14761539
}
14771540
else
14781541
{
@@ -1604,7 +1667,11 @@ private void HandleNMI()
16041667
this.Restart(0x66);
16051668
}
16061669

1607-
private void FetchDisplacement() => this._displacement = (sbyte)this.FetchByte();
1670+
private void FetchDisplacement()
1671+
{
1672+
Debug.Assert(this.M1.Raised(), "Displacement cannot be fetched during an M1 cycle");
1673+
this._displacement = (sbyte)this.FetchByte();
1674+
}
16081675

16091676
// ** From the Z80 CPU User Manual
16101677
// Figure 5 depicts the timing during an M1 (op code fetch) cycle. The Program Counter is
@@ -2341,16 +2408,32 @@ private void WritePort(Register16 port)
23412408
this.WritePort();
23422409
}
23432410

2344-
private void WritePort()
2411+
private void SetIOWrite()
23452412
{
2346-
this.MEMPTR.Assign(this.Bus.Address);
2347-
this.Tick(2);
23482413
this.LowerIORQ();
23492414
this.LowerWR();
2350-
this.Tick();
2351-
this.Ports.Write(this.Bus.Address, this.Bus.Data);
2415+
}
2416+
2417+
private void ResetIOWrite()
2418+
{
23522419
this.RaiseWR();
23532420
this.RaiseIORQ();
2421+
}
2422+
2423+
private void WritePort()
2424+
{
2425+
this.MEMPTR.Assign(this.Bus.Address);
2426+
this.Tick();
2427+
#if CYCLE_ACCURATE
2428+
this.SetIOWrite();
2429+
this.Tick();
2430+
#else
2431+
this.Tick();
2432+
this.SetIOWrite();
2433+
#endif
2434+
this.Tick();
2435+
this.Ports.Write(this.Bus.Address, this.Bus.Data);
2436+
this.ResetIOWrite();
23542437
this.Tick();
23552438
}
23562439

@@ -2367,19 +2450,37 @@ private void ReadPort(Register16 port)
23672450
this.ReadPort();
23682451
}
23692452

2370-
private void ReadPort()
2453+
private void SetIORead()
23712454
{
2372-
this.MEMPTR.Assign(this.Bus.Address);
2373-
this.Tick(2);
23742455
this.LowerIORQ();
23752456
this.LowerRD();
2376-
this.Bus.Data = this.Ports.Read(this.Bus.Address);
2377-
this.Tick();
2457+
}
2458+
2459+
private void ResetIORead()
2460+
{
23782461
this.RaiseRD();
23792462
this.RaiseIORQ();
2463+
2464+
}
2465+
2466+
private void ReadPort()
2467+
{
2468+
this.MEMPTR.Assign(this.Bus.Address);
2469+
this.Tick();
2470+
#if CYCLE_ACCURATE
2471+
this.SetIORead();
2472+
this.Bus.Data = this.Ports.Read(this.Bus.Address);
2473+
this.Tick();
2474+
#else
2475+
this.Tick();
2476+
this.SetIORead();
2477+
this.Bus.Data = this.Ports.Read(this.Bus.Address);
2478+
#endif
2479+
this.Tick();
2480+
this.ResetIORead();
23802481
this.Tick();
23812482
}
23822483

2383-
#endregion
2484+
#endregion
23842485
}
23852486
}

0 commit comments

Comments
 (0)