patch up some savestate issues
[pcsx_rearmed.git] / plugins / dfsound / freeze.c
index 51e9fd7..d4898b4 100644 (file)
@@ -122,9 +122,10 @@ typedef struct
  unsigned short  decode_pos;\r
  uint32_t   pSpuIrq;\r
  uint32_t   spuAddr;\r
- uint32_t   dummy1;\r
- uint32_t   dummy2;\r
- uint32_t   dummy3;\r
+ uint32_t   rvb_cur;\r
+ uint16_t   xa_left;\r
+ uint16_t   cdda_left;\r
+ uint32_t   cycles_played;\r
 \r
  SPUCHAN_orig s_chan[MAXCHAN];   \r
 \r
@@ -132,8 +133,8 @@ typedef struct
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-void LoadStateV5(SPUFreeze_t * pF);                    // newest version\r
-void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles); // unknown format\r
+static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles);\r
+static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles); // unknown format\r
 \r
 // we want to retain compatibility between versions,\r
 // so use original channel struct\r
@@ -228,14 +229,16 @@ static void load_register(unsigned long reg, unsigned int cycles)
 long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,\r
  uint32_t cycles)\r
 {\r
- int i;SPUOSSFreeze_t * pFO;\r
+ SPUOSSFreeze_t * pFO = NULL;\r
+ int i;\r
 \r
  if(!pF) return 0;                                     // first check\r
 \r
- do_samples(cycles, 1);\r
-\r
  if(ulFreezeMode)                                      // info or save?\r
   {//--------------------------------------------------//\r
+   int xa_left = 0, cdda_left = 0;\r
+   do_samples(cycles, 1);\r
+\r
    if(ulFreezeMode==1)                                 \r
     memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t));\r
 \r
@@ -250,10 +253,31 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
    if(spu.xapGlobal && spu.XAPlay!=spu.XAFeed)         // some xa\r
     {\r
-     pF->xaS=*spu.xapGlobal;\r
+     xa_left = spu.XAFeed - spu.XAPlay;\r
+     if (xa_left < 0)\r
+      xa_left = spu.XAEnd - spu.XAPlay + spu.XAFeed - spu.XAStart;\r
+     pF->xaS = *spu.xapGlobal;\r
+    }\r
+   else if (spu.CDDAPlay != spu.CDDAFeed)\r
+    {\r
+     // abuse the xa struct to store leftover cdda samples\r
+     unsigned int *p = spu.CDDAPlay;\r
+     cdda_left = spu.CDDAFeed - spu.CDDAPlay;\r
+     if (cdda_left < 0)\r
+      cdda_left = spu.CDDAEnd - spu.CDDAPlay + spu.CDDAFeed - spu.CDDAStart;\r
+     if (cdda_left > sizeof(pF->xaS.pcm) / 4)\r
+      cdda_left = sizeof(pF->xaS.pcm) / 4;\r
+     if (p + cdda_left <= spu.CDDAEnd)\r
+      memcpy(pF->xaS.pcm, p, cdda_left * 4);\r
+     else {\r
+      memcpy(pF->xaS.pcm, p, (spu.CDDAEnd - p) * 4);\r
+      memcpy((char *)pF->xaS.pcm + (spu.CDDAEnd - p) * 4, spu.CDDAStart,\r
+             (cdda_left - (spu.CDDAEnd - p)) * 4);\r
+     }\r
+     pF->xaS.nsamples = 0;\r
     }\r
-   else \r
-   memset(&pF->xaS,0,sizeof(xa_decode_t));             // or clean xa\r
+   else\r
+    memset(&pF->xaS,0,sizeof(xa_decode_t));            // or clean xa\r
 \r
    pFO=(SPUOSSFreeze_t *)(pF+1);                       // store special stuff\r
 \r
@@ -263,6 +287,10 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
    pFO->spuAddr=spu.spuAddr;\r
    if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d;\r
    pFO->decode_pos = spu.decode_pos;\r
+   pFO->rvb_cur = spu.rvb->CurrAddr;\r
+   pFO->xa_left = xa_left;\r
+   pFO->cdda_left = cdda_left;\r
+   pFO->cycles_played = spu.cycles_played;\r
 \r
    for(i=0;i<MAXCHAN;i++)\r
     {\r
@@ -283,15 +311,22 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
  memcpy(spu.regArea,pF->cSPUPort,0x200);\r
  spu.bMemDirty = 1;\r
 \r
- if(pF->xaS.nsamples<=4032)                            // start xa again\r
-  SPUplayADPCMchannel(&pF->xaS, spu.cycles_played, 0);\r
-\r
- spu.xapGlobal=0;\r
-\r
- if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
-   LoadStateV5(pF);\r
+ if (!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
+   pFO = LoadStateV5(pF, cycles);\r
  else LoadStateUnknown(pF, cycles);\r
 \r
+ spu.XAPlay = spu.XAFeed = spu.XAStart;\r
+ spu.CDDAPlay = spu.CDDAFeed = spu.CDDAStart;\r
+ if (pFO && pFO->xa_left && pF->xaS.nsamples) {        // start xa again\r
+  FeedXA(&pF->xaS);\r
+  spu.XAPlay = spu.XAFeed - pFO->xa_left;\r
+  if (spu.XAPlay < spu.XAStart)\r
+   spu.XAPlay = spu.XAStart;\r
+ }\r
+ else if (pFO && pFO->cdda_left) {                     // start cdda again\r
+  FeedCDDA((void *)pF->xaS.pcm, pFO->cdda_left * 4);\r
+ }\r
+\r
  // repair some globals\r
  for(i=0;i<=62;i+=2)\r
   load_register(H_Reverb+i, cycles);\r
@@ -308,7 +343,6 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
  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
@@ -318,7 +352,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-void LoadStateV5(SPUFreeze_t * pF)\r
+static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles)\r
 {\r
  int i;SPUOSSFreeze_t * pFO;\r
 \r
@@ -332,6 +366,8 @@ void LoadStateV5(SPUFreeze_t * pF)
    else spu.spuAddr = pFO->spuAddr & 0x7fffe;\r
   }\r
  spu.decode_pos = pFO->decode_pos & 0x1ff;\r
+ spu.rvb->CurrAddr = pFO->rvb_cur;\r
+ spu.cycles_played = pFO->cycles_played ? pFO->cycles_played : cycles;\r
 \r
  spu.dwNewChannel=0;\r
  spu.dwChannelsAudible=0;\r
@@ -343,11 +379,12 @@ void LoadStateV5(SPUFreeze_t * pF)
    spu.s_chan[i].pCurr+=(uintptr_t)spu.spuMemC;\r
    spu.s_chan[i].pLoop+=(uintptr_t)spu.spuMemC;\r
   }\r
+ return pFO;\r
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)\r
+static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)\r
 {\r
  int i;\r
 \r
@@ -360,6 +397,7 @@ void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)
  spu.dwChannelsAudible=0;\r
  spu.dwChannelDead=0;\r
  spu.pSpuIrq=spu.spuMemC;\r
+ spu.cycles_played = cycles;\r
 \r
  for(i=0;i<0xc0;i++)\r
   {\r
@@ -368,3 +406,4 @@ void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
+// vim:shiftwidth=1:expandtab\r