[SPU] Emulate SPUSTAT[5:0] as a mirror of SPUCNT[5:0] (#190)
[pcsx_rearmed.git] / plugins / dfsound / freeze.c
index b865b84..43e6535 100644 (file)
@@ -143,12 +143,12 @@ static void save_channel(SPUCHAN_orig *d, const SPUCHAN *s, int ch)
  d->iSBPos = s->iSBPos;\r
  d->spos = s->spos;\r
  d->sinc = s->sinc;\r
- memcpy(d->SB, s->SB, sizeof(d->SB));\r
+ memcpy(d->SB, spu.SB + ch * SB_SIZE, sizeof(d->SB[0]) * SB_SIZE);\r
  d->iStart = (regAreaGet(ch,6)&~1)<<3;\r
  d->iCurr = 0; // set by the caller\r
  d->iLoop = 0; // set by the caller\r
  d->bOn = !!(spu.dwChannelOn & (1<<ch));\r
- d->bStop = s->bStop;\r
+ d->bStop = s->ADSRX.State == ADSR_RELEASE;\r
  d->bReverb = s->bReverb;\r
  d->iActFreq = 1;\r
  d->iUsedFreq = 2;\r
@@ -157,8 +157,8 @@ static void save_channel(SPUCHAN_orig *d, const SPUCHAN *s, int ch)
  d->bIgnoreLoop = (s->prevflags ^ 2) << 1;\r
  d->iRightVolume = s->iRightVolume;\r
  d->iRawPitch = s->iRawPitch;\r
- d->s_1 = s->SB[27]; // yes it's reversed\r
- d->s_2 = s->SB[26];\r
+ d->s_1 = spu.SB[ch * SB_SIZE + 27]; // yes it's reversed\r
+ d->s_2 = spu.SB[ch * SB_SIZE + 26];\r
  d->bRVBActive = s->bRVBActive;\r
  d->bNoise = s->bNoise;\r
  d->bFMod = s->bFMod;\r
@@ -185,10 +185,9 @@ static void load_channel(SPUCHAN *d, const SPUCHAN_orig *s, int ch)
  d->spos = s->spos;\r
  d->sinc = s->sinc;\r
  d->sinc_inv = 0;\r
- memcpy(d->SB, s->SB, sizeof(d->SB));\r
+ memcpy(spu.SB + ch * SB_SIZE, s->SB, sizeof(spu.SB[0]) * SB_SIZE);\r
  d->pCurr = (void *)((long)s->iCurr & 0x7fff0);\r
  d->pLoop = (void *)((long)s->iLoop & 0x7fff0);\r
- d->bStop = s->bStop;\r
  d->bReverb = s->bReverb;\r
  d->iLeftVolume = s->iLeftVolume;\r
  d->iRightVolume = s->iRightVolume;\r
@@ -198,6 +197,7 @@ static void load_channel(SPUCHAN *d, const SPUCHAN_orig *s, int ch)
  d->bFMod = s->bFMod;\r
  d->prevflags = (s->bIgnoreLoop >> 1) ^ 2;\r
  d->ADSRX.State = s->ADSRX.State;\r
+ if (s->bStop) d->ADSRX.State = ADSR_RELEASE;\r
  d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
  d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
  d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
@@ -231,6 +231,8 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
  if(!pF) return 0;                                     // first check\r
 \r
+ do_samples(cycles, 1);\r
+\r
  if(ulFreezeMode)                                      // info or save?\r
   {//--------------------------------------------------//\r
    if(ulFreezeMode==1)                                 \r
@@ -242,8 +244,6 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
    if(ulFreezeMode==2) return 1;                       // info mode? ok, bye\r
                                                        // save mode:\r
-   do_samples(cycles);\r
-\r
    memcpy(pF->cSPURam,spu.spuMem,0x80000);             // copy common infos\r
    memcpy(pF->cSPUPort,spu.regArea,0x200);\r
 \r
@@ -264,11 +264,11 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
    for(i=0;i<MAXCHAN;i++)\r
     {\r
-     save_channel(&pFO->s_chan[i],&s_chan[i],i);\r
-     if(s_chan[i].pCurr)\r
-      pFO->s_chan[i].iCurr=s_chan[i].pCurr-spu.spuMemC;\r
-     if(s_chan[i].pLoop)\r
-      pFO->s_chan[i].iLoop=s_chan[i].pLoop-spu.spuMemC;\r
+     save_channel(&pFO->s_chan[i],&spu.s_chan[i],i);\r
+     if(spu.s_chan[i].pCurr)\r
+      pFO->s_chan[i].iCurr=spu.s_chan[i].pCurr-spu.spuMemC;\r
+     if(spu.s_chan[i].pLoop)\r
+      pFO->s_chan[i].iLoop=spu.s_chan[i].pLoop-spu.spuMemC;\r
     }\r
 \r
    return 1;\r
@@ -279,6 +279,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
  memcpy(spu.spuMem,pF->cSPURam,0x80000);               // get ram\r
  memcpy(spu.regArea,pF->cSPUPort,0x200);\r
+ spu.bMemDirty = 1;\r
 \r
  if(pF->xaS.nsamples<=4032)                            // start xa again\r
   SPUplayADPCMchannel(&pF->xaS);\r
@@ -302,11 +303,14 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
  load_register(H_CDRight, cycles);\r
 \r
  // fix to prevent new interpolations from crashing\r
- for(i=0;i<MAXCHAN;i++) s_chan[i].SB[28]=0;\r
+ for(i=0;i<MAXCHAN;i++) spu.SB[i * SB_SIZE + 28]=0;\r
 \r
  ClearWorkingState();\r
  spu.cycles_played = cycles;\r
 \r
+ if (spu.spuCtrl & CTRL_IRQ)\r
+  schedule_next_irq();\r
+\r
  return 1;\r
 }\r
 \r
@@ -318,12 +322,12 @@ void LoadStateV5(SPUFreeze_t * pF)
 \r
  pFO=(SPUOSSFreeze_t *)(pF+1);\r
 \r
if(pFO->pSpuIrq) spu.pSpuIrq = spu.spuMemC+((long)pFO->pSpuIrq&0x7fff0); else spu.pSpuIrq=NULL;\r
spu.pSpuIrq = spu.spuMemC + ((spu.regArea[(H_SPUirqAddr - 0x0c00) / 2] << 3) & ~0xf);\r
 \r
  if(pFO->spuAddr)\r
   {\r
-   spu.spuAddr = pFO->spuAddr;\r
-   if (spu.spuAddr == 0xbaadf00d) spu.spuAddr = 0;\r
+   if (pFO->spuAddr == 0xbaadf00d) spu.spuAddr = 0;\r
+   else spu.spuAddr = pFO->spuAddr & 0x7fffe;\r
   }\r
 \r
  spu.dwNewChannel=0;\r
@@ -331,10 +335,10 @@ void LoadStateV5(SPUFreeze_t * pF)
  spu.dwChannelDead=0;\r
  for(i=0;i<MAXCHAN;i++)\r
   {\r
-   load_channel(&s_chan[i],&pFO->s_chan[i],i);\r
+   load_channel(&spu.s_chan[i],&pFO->s_chan[i],i);\r
 \r
-   s_chan[i].pCurr+=(unsigned long)spu.spuMemC;\r
-   s_chan[i].pLoop+=(unsigned long)spu.spuMemC;\r
+   spu.s_chan[i].pCurr+=(unsigned long)spu.spuMemC;\r
+   spu.s_chan[i].pLoop+=(unsigned long)spu.spuMemC;\r
   }\r
 }\r
 \r
@@ -346,14 +350,13 @@ void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)
 \r
  for(i=0;i<MAXCHAN;i++)\r
   {\r
-   s_chan[i].bStop=0;\r
-   s_chan[i].pLoop=spu.spuMemC;\r
+   spu.s_chan[i].pLoop=spu.spuMemC;\r
   }\r
 \r
  spu.dwNewChannel=0;\r
  spu.dwChannelOn=0;\r
  spu.dwChannelDead=0;\r
- spu.pSpuIrq=0;\r
+ spu.pSpuIrq=spu.spuMemC;\r
 \r
  for(i=0;i<0xc0;i++)\r
   {\r