spu: change sync again
[pcsx_rearmed.git] / plugins / dfsound / spu.c
index 1456a21..6cefd11 100644 (file)
@@ -444,24 +444,30 @@ static int decode_block(int ch)
 {
  unsigned char *start;
  int predict_nr,shift_factor,flags;
+ int stop = 0;
  int ret = 0;
 
- start=s_chan[ch].pCurr;                   // set up the current pos
+ start = s_chan[ch].pCurr;                 // set up the current pos
+ if(start == spuMemC)                      // ?
+  stop = 1;
 
  if(s_chan[ch].prevflags&1)                // 1: stop/loop
  {
   if(!(s_chan[ch].prevflags&2))
-  {
-   dwChannelOn&=~(1<<ch);                  // -> turn everything off
-   s_chan[ch].bStop=1;
-   s_chan[ch].ADSRX.EnvelopeVol=0;
-  }
+   stop = 1;
 
   start = s_chan[ch].pLoop;
  }
  else
   ret = check_irq(ch, start);              // hack, see check_irq below..
 
+ if(stop)
+ {
+  dwChannelOn &= ~(1<<ch);                 // -> turn everything off
+  s_chan[ch].bStop = 1;
+  s_chan[ch].ADSRX.EnvelopeVol = 0;
+ }
+
  predict_nr=(int)start[0];
  shift_factor=predict_nr&0xf;
  predict_nr >>= 4;
@@ -665,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
@@ -700,8 +707,6 @@ static int do_samples(int forced_updates)
 
  while(!bIRQReturn)
   {
-   cycles_since_update = 0;
-
    ns_from=0;
    ns_to=NSSIZE;
    ch=0;
@@ -770,9 +775,9 @@ static int do_samples(int forced_updates)
 
          // no need for bIRQReturn since the channel is silent
          skip_block(ch);
-         if(start == s_chan[ch].pCurr)
+         if(start == s_chan[ch].pCurr || start - spuMemC < 0x1000)
           {
-           // looping on self
+           // looping on self or stopped(?)
            dwChannelDead |= 1<<ch;
            s_chan[ch].spos = 0;
            break;
@@ -830,6 +835,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: 
@@ -881,8 +888,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;
 }
 
@@ -893,7 +907,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;
 
@@ -908,16 +921,8 @@ 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)) {
+ if(cycles_since_update > PSXCLK/60 * 5/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)
-  do_update = 1;
-
- old_ctrl = spuCtrl;
 
  if(do_update)
   do_samples(forced_updates);