core z80, improve timing for bus request/grant timing from 68k
authorkub <derkub@gmail.com>
Thu, 14 Mar 2024 22:15:16 +0000 (23:15 +0100)
committerkub <derkub@gmail.com>
Thu, 14 Mar 2024 22:18:26 +0000 (23:18 +0100)
pico/memory.c
pico/pico_cmn.c

index 693f960..bedcc1d 100644 (file)
@@ -521,13 +521,19 @@ void NOINLINE ctl_write_z80busreq(u32 d)
   {\r
     if (d)\r
     {\r
-      Pico.t.z80c_cnt = z80_cycles_from_68k() + 1;\r
+      Pico.t.z80c_cnt = z80_cycles_from_68k() + (Pico.t.z80_busdelay >> 8);\r
+      Pico.t.z80_busdelay &= 0xff;\r
     }\r
     else\r
     {\r
       if ((PicoIn.opt & POPT_EN_Z80) && !Pico.m.z80_reset) {\r
+        // Z80 grants bus 2 cycles after the next M cycle, even within an insn\r
+        // simulate this by accumulating the last insn overhang in busdelay\r
+        unsigned granted = z80_cycles_from_68k() + 6;\r
         pprof_start(m68k);\r
         PicoSyncZ80(SekCyclesDone());\r
+        Pico.t.z80_busdelay += (Pico.t.z80c_cnt - granted) << 8;\r
+        Pico.t.z80c_cnt = granted;\r
         pprof_end_sub(m68k);\r
       }\r
     }\r
@@ -553,7 +559,7 @@ void NOINLINE ctl_write_z80reset(u32 d)
     }\r
     else\r
     {\r
-      Pico.t.z80c_cnt = z80_cycles_from_68k() + 1;\r
+      Pico.t.z80c_cnt = z80_cycles_from_68k() + 2;\r
       z80_reset();\r
     }\r
     Pico.m.z80_reset = d;\r
@@ -675,7 +681,8 @@ static void PicoWrite16_sram(u32 a, u32 d)
 static u32 PicoRead8_z80(u32 a)\r
 {\r
   u32 d = 0xff;\r
-  if ((Pico.m.z80Run | Pico.m.z80_reset) && !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) {\r
+  if ((Pico.m.z80Run | Pico.m.z80_reset | (z80_cycles_from_68k() < Pico.t.z80c_cnt)) &&\r
+      !(PicoIn.quirks & PQUIRK_NO_Z80_BUS_LOCK)) {\r
     elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc);\r
     // open bus. Pulled down if MegaCD2 is attached.\r
     return (PicoIn.AHW & PAHW_MCD ? 0 : d);\r
@@ -759,7 +766,7 @@ u32 PicoRead8_io(u32 a)
       // bit8 seems to be readable in this range\r
       if (!(a & 1)) {\r
         d &= ~0x01;\r
-       // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80\r
+        // Z80 ahead of 68K only if in BUSREQ, BUSACK only after 68K reached Z80\r
         d |= (z80_cycles_from_68k() < Pico.t.z80c_cnt);\r
         d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1;\r
         elprintf(EL_BUSREQ, "get_zrun: %02x [%u] @%06x", d, SekCyclesDone(), SekPc);\r
@@ -1356,8 +1363,9 @@ static void access_68k_bus(int delay) // bus delay as Q8
 \r
   // 68k bus access delay for z80. The fractional part needs to be accumulated\r
   // until an additional cycle is full. That is then added to the integer part.\r
-  Pico.t.z80_busdelay = (delay&0xff) + (Pico.t.z80_busdelay&0xff); // accumulate\r
+  Pico.t.z80_busdelay += (delay&0xff); // accumulate\r
   z80_subCLeft((delay>>8) + (Pico.t.z80_busdelay>>8));\r
+  Pico.t.z80_busdelay &= 0xff; // leftover cycle fraction\r
   // don't use SekCyclesBurn() here since the Z80 doesn't run in cycle lock to\r
   // the 68K. Count the stolen cycles to be accounted later in the 68k CPU runs\r
   Pico.t.z80_buscycles += 8;\r
index 29fc82c..c3b14ca 100644 (file)
@@ -80,7 +80,7 @@ static __inline void SekAimM68k(int cyc, int mult)
 
 static __inline void SekRunM68k(int cyc)
 {
-  // TODO 0x100 would by 2 cycles/128, moreover far too sensitive
+  // TODO 0x100 would be 2 cycles/128, moreover far too sensitive
   SekAimM68k(cyc, 0x10c); // OutRunners, testpico, VDPFIFOTesting
   SekSyncM68k(0);
 }