spu: fix thread vs savestates races
authornotaz <notasas@gmail.com>
Tue, 4 Mar 2025 00:02:33 +0000 (02:02 +0200)
committernotaz <notasas@gmail.com>
Tue, 4 Mar 2025 00:02:33 +0000 (02:02 +0200)
plugins/dfsound/freeze.c
plugins/dfsound/spu.c
plugins/dfsound/spu.h

index ae6f16a..b1ab2b5 100644 (file)
@@ -139,6 +139,7 @@ typedef struct
  uint32_t   XALastVal;\r
  uint32_t   last_keyon_cycles;\r
  uint32_t   rvb_sb[2][4];\r
+ int32_t    interpolation; // which interpolation's data is in SPUCHAN_orig::SB\r
 \r
 } SPUOSSFreeze_t;\r
 \r
@@ -238,7 +239,7 @@ static void load_register(unsigned long reg, unsigned int cycles)
 // SPUFREEZE: called by main emu on savestate load/save\r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,\r
+long DoFreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,\r
  unsigned int cycles)\r
 {\r
  SPUOSSFreeze_t * pFO = NULL;\r
@@ -318,6 +319,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
    pFO->last_keyon_cycles = spu.last_keyon_cycles;\r
    for (i = 0; i < 2; i++)\r
     memcpy(&pFO->rvb_sb[i], sb_rvb->SB_rvb[i], sizeof(pFO->rvb_sb[i]));\r
+   pFO->interpolation = spu.interpolation;\r
 \r
    for(i=0;i<MAXCHAN;i++)\r
     {\r
@@ -365,6 +367,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
  spu.XARepeat = 0;\r
  spu.XALastVal = 0;\r
  spu.last_keyon_cycles = cycles - 16*786u;\r
+ spu.interpolation = -1;\r
  if (pFO && pF->ulFreezeSize >= sizeof(*pF) + offsetof(SPUOSSFreeze_t, rvb_sb)) {\r
   spu.cycles_dma_end = pFO->cycles_dma_end;\r
   spu.decode_dirty_ch = pFO->decode_dirty_ch;\r
@@ -378,6 +381,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
   for (i = 0; i < 2; i++)\r
    for (j = 0; j < 2; j++)\r
     memcpy(&sb_rvb->SB_rvb[i][j*4], pFO->rvb_sb[i], 4 * sizeof(sb_rvb->SB_rvb[i][0]));\r
+  spu.interpolation = pFO->interpolation;\r
  }\r
 \r
  // repair some globals\r
@@ -393,8 +397,6 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
  spu.rvb->StartAddr = regAreaGet(H_SPUReverbAddr) << 2;\r
  if (spu.rvb->CurrAddr < spu.rvb->StartAddr)\r
   spu.rvb->CurrAddr = spu.rvb->StartAddr;\r
- // fix to prevent new interpolations from crashing\r
- spu.interpolation = -1;\r
 \r
  ClearWorkingState();\r
 \r
index 0938a34..8159272 100644 (file)
@@ -1574,6 +1574,13 @@ static void exit_spu_thread(void)
 
 #endif
 
+long CALLBACK SPUfreeze(unsigned int ulFreezeMode, struct SPUFreeze * pF,
+ unsigned int cycles)
+{
+ sync_worker_thread(1);
+ return DoFreeze(ulFreezeMode, pF, cycles);
+}
+
 // SPUINIT: this func will be called first by the main emu
 long CALLBACK SPUinit(void)
 {
index d49d903..f2aa9a4 100644 (file)
@@ -42,5 +42,6 @@ void CALLBACK SPUsetCDvol(unsigned char ll, unsigned char lr,
 \r
 // internal\r
 void ClearWorkingState(void);\r
+long DoFreeze(unsigned int, struct SPUFreeze *, unsigned int);\r
 \r
 #endif /* __P_SPU_H__ */\r