spu: handle loop write vs loop flag race (bIgnoreLoop alternative)
authornotaz <notasas@gmail.com>
Thu, 22 Sep 2011 19:38:12 +0000 (22:38 +0300)
committernotaz <notasas@gmail.com>
Thu, 22 Sep 2011 19:38:12 +0000 (22:38 +0300)
it feels this should be better, but shouldn't write much here without
testing really (Heart of Darkness).

plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/registers.c
plugins/dfsound/spu.c

index 4ce39bb..c9f20ca 100644 (file)
@@ -115,6 +115,7 @@ typedef struct
  unsigned int      bRVBActive:1;                       // reverb active flag\r
  unsigned int      bNoise:1;                           // noise active flag\r
  unsigned int      bFMod:2;                            // freq mod (0=off, 1=sound channel, 2=freq channel)\r
+ unsigned int      bJump:1;                            // last decoded block jumped\r
 \r
  int               iLeftVolume;                        // left volume\r
  int               iRightVolume;                       // right volume\r
index 6caa6bf..1c037fe 100644 (file)
@@ -134,6 +134,7 @@ static void save_channel(SPUCHAN_orig *d, const SPUCHAN *s, int ch)
  d->bOn = !!(dwChannelOn & (1<<ch));\r
  d->bStop = s->bStop;\r
  d->bReverb = s->bReverb;\r
+ d->bIgnoreLoop = s->bJump;\r
  d->iActFreq = 1;\r
  d->iUsedFreq = 2;\r
  d->iLeftVolume = s->iLeftVolume;\r
@@ -178,6 +179,7 @@ static void load_channel(SPUCHAN *d, const SPUCHAN_orig *s, int ch)
  d->bRVBActive = s->bRVBActive;\r
  d->bNoise = s->bNoise;\r
  d->bFMod = s->bFMod;\r
+ d->bJump = s->bIgnoreLoop;\r
  d->ADSRX.State = s->ADSRX.State;\r
  d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
  d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
index 2493a1e..669c70f 100644 (file)
@@ -173,6 +173,10 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
      //------------------------------------------------//\r
      case 14:                                          // loop?\r
        s_chan[ch].pLoop=spuMemC+((val&~1)<<3);\r
+       if(s_chan[ch].bJump)\r
+        // real machine would be most likely still doing the last block and use new value for the jump;\r
+        // but we decode ahead a bit and already did the jump part, so compensate for that now.\r
+        s_chan[ch].pCurr=s_chan[ch].pLoop;\r
        break;\r
      //------------------------------------------------//\r
     }\r
@@ -429,6 +433,7 @@ static void SoundOn(int start,int end,unsigned short val)
      s_chan[ch].bStop=0;\r
      s_chan[ch].pCurr=spuMemC+((regAreaGet(ch,6)&~1)<<3); // must be block aligned\r
      s_chan[ch].pLoop=spuMemC+((regAreaGet(ch,14)&~1)<<3);\r
+     s_chan[ch].bJump=0;\r
 \r
      dwNewChannel|=(1<<ch);                            // bitfield for faster testing\r
      dwChannelOn|=1<<ch;\r
index 8c6f7d2..06cc476 100644 (file)
@@ -485,6 +485,7 @@ static int decode_block(int ch)
  }
 
  s_chan[ch].pCurr = start;                 // store values for next cycle
+ s_chan[ch].bJump = flags & 1;
 
  return ret;
 }
@@ -503,13 +504,14 @@ static int skip_block(int ch)
  }
 
  if(flags & 4)
-  s_chan[ch].pLoop=start;
+  s_chan[ch].pLoop = start;
 
  s_chan[ch].pCurr += 16;
 
  if(flags & 1)
   s_chan[ch].pCurr = s_chan[ch].pLoop;
 
+ s_chan[ch].bJump = flags & 1;
  return ret;
 }