spu: add a schedule callback
[pcsx_rearmed.git] / plugins / dfsound / spu.c
index a190b29..7d3f1a0 100644 (file)
@@ -671,12 +671,13 @@ static void noinline do_decode_bufs(int which, int start, int count)
 {
  const int *src = ChanBuf + start;
  unsigned short *dst = &spuMem[0x800/2 + which*0x400/2];
- int cursor = decode_pos;
+ int cursor = decode_pos + start;
 
  while (count-- > 0)
   {
+   cursor &= 0x1ff;
    dst[cursor] = *src++;
-   cursor = (cursor + 1) & 0x1ff;
+   cursor++;
   }
 
  // decode_pos is updated and irqs are checked later, after voice loop
@@ -691,7 +692,7 @@ static void noinline do_decode_bufs(int which, int start, int count)
 static int do_samples(int forced_updates)
 {
  int volmult = iVolume;
- int ns,ns_from,ns_to;
+ int ns,ns_from,ns_to,ns_len;
  int ch,d,silentch;
  int bIRQReturn=0;
 
@@ -706,8 +707,6 @@ static int do_samples(int forced_updates)
 
  while(!bIRQReturn)
   {
-   cycles_since_update = 0;
-
    ns_from=0;
    ns_to=NSSIZE;
    ch=0;
@@ -741,21 +740,22 @@ static int do_samples(int forced_updates)
          lastch=ch; 
          lastns=ns_to=d;
         }
+       ns_len = ns_to - ns_from;
 
        MixADSR(ch, ns_from, ns_to);
 
        if(ch==1 || ch==3)
         {
-         do_decode_bufs(ch/2, ns_from, ns_to-ns_from);
+         do_decode_bufs(ch/2, ns_from, ns_len);
          decode_dirty_ch |= 1<<ch;
         }
 
        if(s_chan[ch].bFMod==2)                         // fmod freq channel
-        memcpy(iFMod, ChanBuf, sizeof(iFMod));
-       else if(s_chan[ch].bRVBActive)
-        mix_chan_rvb(ns_from,ns_to-ns_from,s_chan[ch].iLeftVolume,s_chan[ch].iRightVolume);
+        memcpy(&iFMod[ns_from], &ChanBuf[ns_from], ns_len * sizeof(iFMod[0]));
+       if(s_chan[ch].bRVBActive)
+        mix_chan_rvb(ns_from, ns_len, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume);
        else
-        mix_chan(ns_from,ns_to-ns_from,s_chan[ch].iLeftVolume,s_chan[ch].iRightVolume);
+        mix_chan(ns_from, ns_len, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume);
       }
     }
 
@@ -836,6 +836,8 @@ static int do_samples(int forced_updates)
     ns++;
    }
 
+   cycles_since_update -= PSXCLK / 44100 * NSSIZE;
+
   //////////////////////////////////////////////////////                   
   // special irq handling in the decode buffers (0x0000-0x1000)
   // we know: 
@@ -887,8 +889,15 @@ static int do_samples(int forced_updates)
     if(forced_updates == 0 && out_current->busy())
      break;
    }
+
+  if(cycles_since_update <= -PSXCLK/60 / 4)
+   break;
  }
 
+ // this may cause desync, but help audio when the emu can't keep up..
+ if(cycles_since_update < 0)
+  cycles_since_update = 0;
+
  return 0;
 }
 
@@ -899,7 +908,6 @@ static int do_samples(int forced_updates)
 
 void CALLBACK SPUasync(unsigned long cycle)
 {
- static int old_ctrl;
  int forced_updates = 0;
  int do_update = 0;
 
@@ -914,17 +922,9 @@ void CALLBACK SPUasync(unsigned long cycle)
    had_dma = 0;
   }
 
- if((spuCtrl&CTRL_IRQ) && (((spuCtrl^old_ctrl)&CTRL_IRQ) // irq was enabled
-    || cycles_since_update > PSXCLK/60 / 4)) {
-  do_update = 1;
-  forced_updates = cycles_since_update / (PSXCLK/44100) / NSSIZE;
- }
- // with no irqs, once per frame should be fine (using a bit more because of BIAS)
- else if(cycles_since_update > PSXCLK/60 * 5/4)
+ if(cycles_since_update > PSXCLK/60 * 5/4)
   do_update = 1;
 
- old_ctrl = spuCtrl;
-
  if(do_update)
   do_samples(forced_updates);
 }
@@ -1121,6 +1121,10 @@ void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned shor
  cddavCallback = CDDAVcallback;
 }
 
+void CALLBACK SPUregisterScheduleCb(void (CALLBACK *callback)(unsigned int))
+{
+}
+
 // COMMON PLUGIN INFO FUNCS
 /*
 char * CALLBACK PSEgetLibName(void)