core, improve 68K/Z80 timing
authorkub <derkub@gmail.com>
Mon, 24 Apr 2023 21:50:06 +0000 (23:50 +0200)
committerkub <derkub@gmail.com>
Mon, 24 Apr 2023 21:50:06 +0000 (23:50 +0200)
pico/memory.c
pico/pico.c
pico/pico_cmn.c

index b268e85..e7c3d53 100644 (file)
@@ -325,7 +325,7 @@ static NOINLINE u32 port_read(int i)
   out = data_reg & ctrl_reg;\r
 \r
   // pull-ups: should be 0x7f, but Decap Attack has a bug where it temp.\r
-  // disables output before doing TH-low read, so don't emulate it for TH.\r
+  // disables output before doing TH-low read, so emulate RC filter for TH.\r
   // Decap Attack reportedly doesn't work on Nomad but works on must\r
   // other MD revisions (different pull-up strength?).\r
   u32 mask = 0x3f;\r
@@ -599,9 +599,10 @@ static u32 PicoRead8_z80(u32 a)
     return 0;\r
   }\r
 \r
-  if ((a & 0x4000) == 0x0000)\r
+  if ((a & 0x4000) == 0x0000) {\r
+    SekCyclesBurnRun(1);\r
     d = PicoMem.zram[a & 0x1fff];\r
-  else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff\r
+  else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff\r
     d = ym2612_read_local_68k(); \r
   else\r
     elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc);\r
@@ -623,6 +624,7 @@ static void PicoWrite8_z80(u32 a, u32 d)
   }\r
 \r
   if ((a & 0x4000) == 0x0000) { // z80 RAM\r
+    SekCyclesBurnRun(1);\r
     PicoMem.zram[a & 0x1fff] = (u8)d;\r
     return;\r
   }\r
@@ -1269,9 +1271,10 @@ void PicoWrite16_32x(u32 a, u32 d) {}
 \r
 static unsigned char z80_md_vdp_read(unsigned short a)\r
 {\r
-  z80_subCLeft(2);\r
+  if ((a & 0xff00) == 0x7f00) {\r
+    z80_subCLeft(3);\r
+    Pico.t.z80_buscycles += 7;\r
 \r
-  if ((a & 0x00f0) == 0x0000) {\r
     switch (a & 0x0d)\r
     {\r
       case 0x00: return PicoVideoRead8DataH(1);\r
index 0bfcb9f..8be65a0 100644 (file)
@@ -187,7 +187,7 @@ int PicoReset(void)
   PsndReset(); // pal must be known here\r
 \r
   // create an empty "dma" to cause 68k exec start at random frame location\r
-  Pico.t.m68c_line_start = Pico.t.m68c_cnt;\r
+  Pico.t.m68c_line_start = Pico.t.m68c_aim;\r
   PicoVideoFIFOWrite(rand() & 0x1fff, 0, 0, PVS_CPURD);\r
 \r
   SekFinishIdleDet();\r
index 4cffc55..f2a3c22 100644 (file)
@@ -47,9 +47,9 @@ static void SekSyncM68k(void)
 
   while ((cyc_do = Pico.t.m68c_aim - Pico.t.m68c_cnt) > 0) {
     // the Z80 CPU is stealing some bus cycles from the 68K main CPU when 
-    // accessing the 68K RAM or ROM. Account for these by shortening the time
+    // accessing the main bus. Account for these by shortening the time
     // the 68K CPU runs.
-    int z80_buscyc = Pico.t.z80_buscycles;
+    int z80_buscyc = Pico.t.z80_buscycles >> (~Pico.m.scanline & 1);
     if (z80_buscyc <= cyc_do)
       SekExecM68k(cyc_do - z80_buscyc);
     else
@@ -65,8 +65,12 @@ static void SekSyncM68k(void)
 
 static __inline void SekRunM68k(int cyc)
 {
+  // refresh slowdown handling, 2 cycles every 128 - make this 1 every 64
+  // NB must be quite accurate, so handle fractions as well (c/f OutRunners)
+  static int refresh;
+  Pico.t.m68c_cnt += (cyc + refresh) >> 6;
+  refresh = (cyc + refresh) & 0x3f;
   Pico.t.m68c_aim += cyc;
-  Pico.t.m68c_cnt += cyc >> 6; // refresh slowdowns
 
   SekSyncM68k();
 }
@@ -101,8 +105,10 @@ static void do_timing_hacks_end(struct PicoVideo *pv)
   PicoVideoFIFOSync(CYCLES_M68K_LINE);
 
   // need rather tight Z80 sync for emulation of main bus cycle stealing
-  if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80) && (Pico.m.scanline&1))
-    PicoSyncZ80(Pico.t.m68c_aim);
+  if (Pico.m.scanline&1) {
+    if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoIn.opt&POPT_EN_Z80))
+      PicoSyncZ80(Pico.t.m68c_aim);
+  }
 }
 
 static void do_timing_hacks_start(struct PicoVideo *pv)