-static __inline void check_cd_dma(void)
-{
- int ddx;
-
- if (!(Pico_mcd->scd.Status_CDC & 0x08)) return;
-
- ddx = Pico_mcd->s68k_regs[4] & 7;
- if (ddx < 2) return; // invalid
- if (ddx < 4) {
- Pico_mcd->s68k_regs[4] |= 0x40; // Data set ready in host port
- return;
- }
- if (ddx == 6) return; // invalid
-
- Update_CDC_TRansfer(ddx); // now go and do the actual transfer
-}
-
-static __inline void update_chips(void)
-{
- int counter_timer, int3_set;
- int counter75hz_lim = Pico.m.pal ? 2080 : 2096;
-
- // 75Hz CDC update
- if ((Pico_mcd->m.counter75hz+=10) >= counter75hz_lim) {
- Pico_mcd->m.counter75hz -= counter75hz_lim;
- Check_CD_Command();
- }
-
- // update timers
- counter_timer = Pico.m.pal ? 0x21630 : 0x2121c; // 136752 : 135708;
- Pico_mcd->m.timer_stopwatch += counter_timer;
- if ((int3_set = Pico_mcd->s68k_regs[0x31])) {
- Pico_mcd->m.timer_int3 -= counter_timer;
- if (Pico_mcd->m.timer_int3 < 0) {
- if (Pico_mcd->s68k_regs[0x33] & (1<<3)) {
- elprintf(EL_INTS, "s68k: timer irq 3");
- SekInterruptS68k(3);
- Pico_mcd->m.timer_int3 += int3_set << 16;
- }
- // is this really what happens if irq3 is masked out?
- Pico_mcd->m.timer_int3 &= 0xffffff;
- }
- }
-
- // update gfx chip
- if (Pico_mcd->rot_comp.Reg_58 & 0x8000)
- gfx_cd_update();
-
- // delayed setting of DMNA bit (needed for Silpheed)
- if (Pico_mcd->m.state_flags & 2) {
- Pico_mcd->m.state_flags &= ~2;
- if (!(Pico_mcd->s68k_regs[3] & 4)) {
- Pico_mcd->s68k_regs[3] |= 2;
- Pico_mcd->s68k_regs[3] &= ~1;
-#ifdef USE_POLL_DETECT
- if ((s68k_poll_adclk&0xfe) == 2) {
- SekSetStopS68k(0); s68k_poll_adclk = 0;
- }
-#endif
- }
- }
+typedef void (event_cb)(unsigned int now);
+
+/* times are in s68k (12.5MHz) cycles */
+unsigned int pcd_event_times[PCD_EVENT_COUNT];
+static unsigned int event_time_next;
+static event_cb *pcd_event_cbs[PCD_EVENT_COUNT] = {
+ [PCD_EVENT_CDC] = pcd_cdc_event,
+ [PCD_EVENT_TIMER3] = pcd_int3_timer_event,
+ [PCD_EVENT_GFX] = pcd_gfx_event,
+ [PCD_EVENT_DMA] = pcd_dma_event,
+};
+
+void pcd_event_schedule(unsigned int now, enum pcd_event event, int after)
+{
+ unsigned int when;
+
+ when = now + after;
+ if (when == 0) {
+ // event cancelled
+ pcd_event_times[event] = 0;
+ return;
+ }
+
+ when |= 1;
+
+ elprintf(EL_CD, "cd: new event #%u %u->%u", event, now, when);
+ pcd_event_times[event] = when;
+
+ if (event_time_next == 0 || CYCLES_GT(event_time_next, when))
+ event_time_next = when;