32x: fix some more timing problems
[picodrive.git] / pico / 32x / 32x.c
index 7a4d7b3..ed0c210 100644 (file)
@@ -29,11 +29,10 @@ static int REGPARM(2) sh2_irq_cb(SH2 *sh2, int level)
   }
 }
 
-// if !nested_call, must sync CPUs before calling this
-void p32x_update_irls(SH2 *active_sh2)
+// MUST specify active_sh2 when called from sh2 memhandlers
+void p32x_update_irls(SH2 *active_sh2, int m68k_cycles)
 {
   int irqs, mlvl = 0, slvl = 0;
-  int m68k_cycles = 0;
   int mrun, srun;
 
   if (active_sh2 != NULL)
@@ -51,13 +50,19 @@ void p32x_update_irls(SH2 *active_sh2)
     slvl++;
   slvl *= 2;
 
-  mrun = sh2_irl_irq(&msh2, mlvl, active_sh2 != NULL);
-  if (mrun)
+  mrun = sh2_irl_irq(&msh2, mlvl, active_sh2 == &msh2);
+  if (mrun) {
     p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, m68k_cycles);
+    if (active_sh2 == &msh2)
+      sh2_end_run(active_sh2, 1);
+  }
 
-  srun = sh2_irl_irq(&ssh2, slvl, active_sh2 != NULL);
-  if (srun)
+  srun = sh2_irl_irq(&ssh2, slvl, active_sh2 == &ssh2);
+  if (srun) {
     p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, m68k_cycles);
+    if (active_sh2 == &ssh2)
+      sh2_end_run(active_sh2, 1);
+  }
 
   elprintf(EL_32X, "update_irls: m %d/%d, s %d/%d", mlvl, mrun, slvl, srun);
 }
@@ -74,6 +79,7 @@ void Pico32xStartup(void)
   ssh2.irq_callback = sh2_irq_cb;
 
   PicoMemSetup32x();
+  p32x_pwm_ctl_changed();
   p32x_timers_recalc();
 
   if (!Pico.m.pal)
@@ -169,9 +175,10 @@ void PicoReset32x(void)
 {
   if (PicoAHW & PAHW_32X) {
     Pico32x.sh2irqs |= P32XI_VRES;
-    p32x_update_irls(NULL);
+    p32x_update_irls(NULL, SekCyclesDoneT2());
     p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, 0);
     p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, 0);
+    p32x_pwm_ctl_changed();
     p32x_timers_recalc();
   }
 }
@@ -216,7 +223,7 @@ static void p32x_start_blank(void)
   }
 
   Pico32x.sh2irqs |= P32XI_VINT;
-  p32x_update_irls(NULL);
+  p32x_update_irls(NULL, SekCyclesDoneT2());
   p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0);
   p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0);
 }
@@ -268,8 +275,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after)
   p32x_event_schedule(now, event, after);
 
   left_to_next = (event_time_next - now) * 3;
-  if (sh2_cycles_left(sh2) > left_to_next)
-    sh2_end_run(sh2, left_to_next);
+  sh2_end_run(sh2, left_to_next);
 }
 
 static void run_events(unsigned int until)
@@ -433,7 +439,7 @@ void sync_sh2s_normal(unsigned int m68k_target)
       }
     }
 
-    p32x_timers_do(now, now - timer_cycles);
+    p32x_timers_do(now - timer_cycles);
     timer_cycles = now;
   }
 
@@ -515,7 +521,7 @@ void Pico32xStateLoaded(int is_early)
 
   SekCycleCnt = 0;
   sh2s[0].m68krcycles_done = sh2s[1].m68krcycles_done = SekCycleCntT;
-  p32x_update_irls(NULL);
+  p32x_update_irls(NULL, SekCycleCntT);
   p32x_pwm_state_loaded();
   run_events(SekCycleCntT);
 }