32x, improve poll detection
authorkub <derkub@gmail.com>
Sat, 3 Jun 2023 07:49:17 +0000 (07:49 +0000)
committerkub <derkub@gmail.com>
Sat, 3 Jun 2023 07:49:17 +0000 (07:49 +0000)
pico/32x/32x.c
pico/32x/memory.c
pico/32x/sh2soc.c
pico/pico_int.h

index b630904..8b91c7b 100644 (file)
@@ -54,14 +54,14 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles)
 
   mrun = sh2_irl_irq(&msh2, mlvl, msh2.state & SH2_STATE_RUN);
   if (mrun) {
-    p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles);
+    p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles);
     if (msh2.state & SH2_STATE_RUN)
       sh2_end_run(&msh2, 0);
   }
 
   srun = sh2_irl_irq(&ssh2, slvl, ssh2.state & SH2_STATE_RUN);
   if (srun) {
-    p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles);
+    p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_IDLE_STATES & ~SH2_STATE_SLEEP, m68k_cycles);
     if (ssh2.state & SH2_STATE_RUN)
       sh2_end_run(&ssh2, 0);
   }
@@ -207,8 +207,8 @@ void PicoReset32x(void)
 {
   if (PicoIn.AHW & PAHW_32X) {
     p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VRES);
-    p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, SekCyclesDone());
-    p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, SekCyclesDone());
+    p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_IDLE_STATES, SekCyclesDone());
+    p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_IDLE_STATES, SekCyclesDone());
     p32x_pwm_ctl_changed();
     p32x_timers_recalc();
     Pico32x.vdp_regs[0] &= ~P32XV_Mx; // 32X graphics disabled
@@ -256,8 +256,8 @@ static void p32x_start_blank(void)
   }
 
   p32x_trigger_irq(NULL, Pico.t.m68c_aim, P32XI_VINT);
-  p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
-  p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
+  p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
+  p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
 }
 
 static void p32x_end_blank(void)
@@ -267,10 +267,10 @@ static void p32x_end_blank(void)
   if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0) // no forced blanking
     Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access
   if (!(Pico32x.sh2_regs[0] & 0x80))
-    p32x_schedule_hint(NULL, SekCyclesDone());
+    p32x_schedule_hint(NULL, Pico.t.m68c_aim);
 
-  p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
-  p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
+  p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
+  p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, Pico.t.m68c_aim);
 }
 
 void p32x_schedule_hint(SH2 *sh2, unsigned int m68k_cycles)
@@ -293,8 +293,8 @@ void p32x_schedule_hint(SH2 *sh2, unsigned int m68k_cycles)
 static void fillend_event(unsigned int now)
 {
   Pico32x.vdp_regs[0x0a/2] &= ~P32XV_nFEN;
-  p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, now);
-  p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, now);
+  p32x_sh2_poll_event(msh2.poll_addr, &msh2, SH2_STATE_VPOLL, now);
+  p32x_sh2_poll_event(ssh2.poll_addr, &ssh2, SH2_STATE_VPOLL, now);
 }
 
 static void hint_event(unsigned int now)
index 21381c9..a8d2e60 100644 (file)
@@ -70,7 +70,7 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
 {
   int ret = 0;
   // support polling on 2 addresses - seen in Wolfenstein
-  int match = (a - m68k_poll.addr1 <= 2 || a - m68k_poll.addr2 <= 2);
+  int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3);
 
   if (match && cycles - m68k_poll.cycles <= 64 && !SekNotPolling)
   {
@@ -91,7 +91,7 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
     m68k_poll.cnt = 0;
     if (!match) {
       m68k_poll.addr2 = m68k_poll.addr1;
-      m68k_poll.addr1 = a;
+      m68k_poll.addr1 = a & ~1;
     }
     SekNotPolling = 0;
   }
@@ -100,15 +100,19 @@ static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
   return ret;
 }
 
-void p32x_m68k_poll_event(u32 flags)
+void p32x_m68k_poll_event(u32 a, u32 flags)
 {
-  if (Pico32x.emu_flags & flags) {
+  int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3);
+
+  if ((Pico32x.emu_flags & flags) && match) {
     elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags,
       Pico32x.emu_flags & ~flags);
     Pico32x.emu_flags &= ~flags;
     SekSetStop(0);
   }
-  m68k_poll.addr1 = m68k_poll.addr2 = m68k_poll.cnt = 0;
+
+  if (!(Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL)))
+    m68k_poll.addr1 = m68k_poll.addr2 = m68k_poll.cnt = 0;
 }
 
 void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt)
@@ -116,10 +120,11 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt)
   u32 cycles_done = sh2_cycles_done_t(sh2);
   u32 cycles_diff = cycles_done - sh2->poll_cycles;
 
+  a &= ~0x20000000;
   // reading 2 consecutive 16bit values is probably a 32bit access. detect this
   // by checking address (max 2 bytes away) and cycles (max 2 cycles later).
   // no polling if more than 20 cycles have passed since last detect call.
-  if (a - sh2->poll_addr <= 2 && CYCLES_GE(20, cycles_diff)) {
+  if (a - sh2->poll_addr <= 3 && CYCLES_GE(20, cycles_diff)) {
     if (!sh2_not_polling(sh2) && CYCLES_GT(cycles_diff, 2) &&
                 ++sh2->poll_cnt >= maxcnt) {
       if (!(sh2->state & flags))
@@ -142,15 +147,16 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt)
   }
   else if (!(sh2->state & (SH2_STATE_CPOLL|SH2_STATE_VPOLL|SH2_STATE_RPOLL))) {
     sh2->poll_cnt = 0;
-    sh2->poll_addr = a;
+    sh2->poll_addr = a & ~1;
   }
   sh2->poll_cycles = cycles_done;
   sh2_set_polling(sh2);
 }
 
-void NOINLINE p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles)
+void NOINLINE p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles)
 {
-  if (sh2->state & flags) {
+  a &= ~0x20000000;
+  if ((sh2->state & flags) && a - sh2->poll_addr <= 3) {
     elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state,
       sh2->state & ~flags);
 
@@ -518,8 +524,8 @@ static void p32x_reg_write8(u32 a, u32 d)
 
         if (REG8IN16(r, a) != (u8)d) {
           REG8IN16(r, a) = d;
-          p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
-          p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
+          p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles);
+          p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles);
           sh2_poll_write(a & ~1, r[a / 2], cycles, NULL);
         }
       }
@@ -616,8 +622,8 @@ static void p32x_reg_write16(u32 a, u32 d)
 
         if (r[a / 2] != (u16)d) {
           r[a / 2] = d;
-          p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
-          p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
+          p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles);
+          p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles);
           sh2_poll_write(a, (u16)d, cycles, NULL);
         }
       }
@@ -772,7 +778,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
     case 0x2a/2:
     case 0x2c/2:
     case 0x2e/2:
-      p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5);
+      p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9);
       cycles = sh2_cycles_done_m68k(sh2);
       sh2s_sync_on_read(sh2, cycles);
       return sh2_poll_read(a, r[a / 2], cycles, sh2);
@@ -828,7 +834,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
       if (Pico32x.sh2_regs[4 / 2] != (u8)d) {
         unsigned int cycles = sh2_cycles_done_m68k(sh2);
         Pico32x.sh2_regs[4 / 2] = d;
-        p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
+        p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
           sh2_end_run(sh2, 4);
         sh2_poll_write(a & ~1, d, cycles, sh2);
@@ -854,8 +860,8 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
         unsigned int cycles = sh2_cycles_done_m68k(sh2);
 
         REG8IN16(r, a) = d;
-        p32x_m68k_poll_event(P32XF_68KCPOLL);
-        p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
+        p32x_m68k_poll_event(a, P32XF_68KCPOLL);
+        p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
           sh2_end_run(sh2, 0);
         sh2_poll_write(a & ~1, r[a / 2], cycles, sh2);
@@ -947,8 +953,8 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
         unsigned int cycles = sh2_cycles_done_m68k(sh2);
 
         Pico32x.regs[a / 2] = d;
-        p32x_m68k_poll_event(P32XF_68KCPOLL);
-        p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
+        p32x_m68k_poll_event(a, P32XF_68KCPOLL);
+        p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
           sh2_end_run(sh2, 0);
         sh2_poll_write(a, d, cycles, sh2);
@@ -1579,7 +1585,7 @@ static void sh2_sdram_poll(u32 a, u32 d, SH2 *sh2)
   DRC_SAVE_SR(sh2);
   cycles = sh2_cycles_done_m68k(sh2);
   sh2_poll_write(a, d, cycles, sh2);
-  p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_RPOLL, cycles);
+  p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_RPOLL, cycles);
   if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
     sh2_end_run(sh2, 0);
   DRC_RESTORE_SR(sh2);
index 852f394..fb1cf1e 100644 (file)
@@ -76,7 +76,7 @@ static void dmac_transfer_complete(SH2 *sh2, struct dma_chan *chan)
 {
   chan->chcr |= DMA_TE; // DMA has ended normally
 
-  p32x_sh2_poll_event(sh2, SH2_STATE_SLEEP, SekCyclesDone());
+  p32x_sh2_poll_event(sh2->poll_addr, sh2, SH2_STATE_SLEEP, SekCyclesDone());
   if (chan->chcr & DMA_IE)
     dmac_te_irq(sh2, chan);
 }
@@ -390,7 +390,7 @@ void REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, SH2 *sh2)
     break;
   default:
     if ((a & 0x1c0) == 0x140)
-      p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone());
+      p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone());
   }
   DRC_RESTORE_SR(sh2);
 }
@@ -416,7 +416,7 @@ void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2)
   } else {
     r[MEM_BE2(a / 2)] = d;
     if ((a & 0x1c0) == 0x140)
-      p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone());
+      p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone());
   }
   DRC_RESTORE_SR(sh2);
 }
@@ -484,7 +484,7 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2)
       break;
     default:
       if ((a & 0x1c0) == 0x140)
-        p32x_sh2_poll_event(sh2, SH2_STATE_CPOLL, SekCyclesDone());
+        p32x_sh2_poll_event(a, sh2, SH2_STATE_CPOLL, SekCyclesDone());
   }
 
   DRC_RESTORE_SR(sh2);
index ad018fa..7a697ed 100644 (file)
@@ -1020,14 +1020,14 @@ void PicoMemSetup32x(void);
 void Pico32xSwapDRAM(int b);\r
 void Pico32xMemStateLoaded(void);\r
 void p32x_update_banks(void);\r
-void p32x_m68k_poll_event(u32 flags);\r
+void p32x_m68k_poll_event(u32 a, u32 flags);\r
 u32 REGPARM(3) p32x_sh2_poll_memory8(u32 a, u32 d, SH2 *sh2);\r
 u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2);\r
 u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2);\r
 void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2);\r
 int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2);\r
 void p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt);\r
-void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles);\r
+void p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles);\r
 int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2);\r
 \r
 // 32x/draw.c\r