32x: memhandler improvements
[picodrive.git] / pico / 32x / 32x.c
index 339a852..d0110c1 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);
 }
@@ -68,19 +73,20 @@ void Pico32xStartup(void)
 
   // TODO: OOM handling
   PicoAHW |= PAHW_32X;
-  sh2_init(&msh2, 0);
+  sh2_init(&msh2, 0, &ssh2);
   msh2.irq_callback = sh2_irq_cb;
-  sh2_init(&ssh2, 1);
+  sh2_init(&ssh2, 1, &msh2);
   ssh2.irq_callback = sh2_irq_cb;
 
   PicoMemSetup32x();
+  p32x_pwm_ctl_changed();
   p32x_timers_recalc();
 
   if (!Pico.m.pal)
     Pico32x.vdp_regs[0] |= P32XV_nPAL;
 
-  PREG8(Pico32xMem->sh2_peri_regs[0], 4) =
-  PREG8(Pico32xMem->sh2_peri_regs[1], 4) = 0x84; // SCI SSR
+  PREG8(msh2.peri_regs, 4) =
+  PREG8(ssh2.peri_regs, 4) = 0x84; // SCI SSR
 
   rendstatus_old = -1;
 
@@ -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);
 }
@@ -230,15 +237,6 @@ static void p32x_start_blank(void)
   ((int)((a) - (b)) >= 0)
 
 /* events */
-static void pwm_irq_event(unsigned int now)
-{
-  Pico32x.emu_flags &= ~P32XF_PWM_PEND;
-  p32x_pwm_schedule(now);
-
-  Pico32x.sh2irqs |= P32XI_PWM;
-  p32x_update_irls(NULL);
-}
-
 static void fillend_event(unsigned int now)
 {
   Pico32x.vdp_regs[0x0a/2] &= ~P32XV_nFEN;
@@ -251,7 +249,7 @@ typedef void (event_cb)(unsigned int now);
 unsigned int event_times[P32X_EVENT_COUNT];
 static unsigned int event_time_next;
 static event_cb *event_cbs[] = {
-  [P32X_EVENT_PWM]      = pwm_irq_event,
+  [P32X_EVENT_PWM]      = p32x_pwm_irq_event,
   [P32X_EVENT_FILLEND]  = fillend_event,
 };
 
@@ -277,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)
@@ -342,7 +339,7 @@ static inline void run_sh2(SH2 *sh2, int m68k_cycles)
 // note: recursive call
 void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target)
 {
-  SH2 *osh2 = &sh2s[sh2->is_slave ^ 1];
+  SH2 *osh2 = sh2->other_sh2;
   int left_to_event;
   int m68k_cycles;
 
@@ -524,8 +521,8 @@ void Pico32xStateLoaded(int is_early)
 
   SekCycleCnt = 0;
   sh2s[0].m68krcycles_done = sh2s[1].m68krcycles_done = SekCycleCntT;
-  p32x_update_irls(NULL);
-  p32x_timers_recalc();
+  p32x_update_irls(NULL, SekCycleCntT);
+  p32x_pwm_state_loaded();
   run_events(SekCycleCntT);
 }