spu: clean up unneeded code
[pcsx_rearmed.git] / plugins / dfsound / freeze.c
CommitLineData
ef79bbde
P
1/***************************************************************************\r
2 freeze.c - description\r
3 -------------------\r
4 begin : Wed May 15 2002\r
5 copyright : (C) 2002 by Pete Bernert\r
6 email : BlackDove@addcom.de\r
7 ***************************************************************************/\r
8/***************************************************************************\r
9 * *\r
10 * This program is free software; you can redistribute it and/or modify *\r
11 * it under the terms of the GNU General Public License as published by *\r
12 * the Free Software Foundation; either version 2 of the License, or *\r
13 * (at your option) any later version. See also the license.txt file for *\r
14 * additional informations. *\r
15 * *\r
16 ***************************************************************************/\r
17\r
18#include "stdafx.h"\r
19\r
20#define _IN_FREEZE\r
21\r
22#include "externals.h"\r
23#include "registers.h"\r
24#include "spu.h"\r
ef79bbde
P
25\r
26////////////////////////////////////////////////////////////////////////\r
27// freeze structs\r
28////////////////////////////////////////////////////////////////////////\r
29\r
6d866bb7 30typedef struct\r
31{\r
32 int State;\r
33 int AttackModeExp;\r
34 int AttackRate;\r
35 int DecayRate;\r
36 int SustainLevel;\r
37 int SustainModeExp;\r
38 int SustainIncrease;\r
39 int SustainRate;\r
40 int ReleaseModeExp;\r
41 int ReleaseRate;\r
42 int EnvelopeVol;\r
43 long lVolume;\r
44 long lDummy1;\r
45 long lDummy2;\r
46} ADSRInfoEx_orig;\r
47\r
48typedef struct\r
49{\r
50 // no mutexes used anymore... don't need them to sync access\r
51 //HANDLE hMutex;\r
52\r
53 int bNew; // start flag\r
54\r
55 int iSBPos; // mixing stuff\r
56 int spos;\r
57 int sinc;\r
58 int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :)\r
59 int sval;\r
60\r
61 unsigned char * pStart; // start ptr into sound mem\r
62 unsigned char * pCurr; // current pos in sound mem\r
63 unsigned char * pLoop; // loop ptr in sound mem\r
64\r
65 int bOn; // is channel active (sample playing?)\r
66 int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase)\r
67 int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active\r
68 int iActFreq; // current psx pitch\r
69 int iUsedFreq; // current pc pitch\r
70 int iLeftVolume; // left volume\r
71 int iLeftVolRaw; // left psx volume value\r
72 int bIgnoreLoop; // ignore loop bit, if an external loop address is used\r
73 int iMute; // mute mode\r
74 int iRightVolume; // right volume\r
75 int iRightVolRaw; // right psx volume value\r
76 int iRawPitch; // raw pitch (0...3fff)\r
77 int iIrqDone; // debug irq done flag\r
78 int s_1; // last decoding infos\r
79 int s_2;\r
80 int bRVBActive; // reverb active flag\r
81 int iRVBOffset; // reverb offset\r
82 int iRVBRepeat; // reverb repeat\r
83 int bNoise; // noise active flag\r
84 int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel)\r
85 int iRVBNum; // another reverb helper\r
86 int iOldNoise; // old noise val for this channel \r
87 ADSRInfo ADSR; // active ADSR settings\r
88 ADSRInfoEx_orig ADSRX; // next ADSR settings (will be moved to active on sample start)\r
89} SPUCHAN_orig;\r
90\r
ef79bbde
P
91typedef struct\r
92{\r
93 char szSPUName[8];\r
94 uint32_t ulFreezeVersion;\r
95 uint32_t ulFreezeSize;\r
96 unsigned char cSPUPort[0x200];\r
97 unsigned char cSPURam[0x80000];\r
98 xa_decode_t xaS; \r
99} SPUFreeze_t;\r
100\r
101typedef struct\r
102{\r
103 unsigned short spuIrq;\r
104 uint32_t pSpuIrq;\r
105 uint32_t spuAddr;\r
106 uint32_t dummy1;\r
107 uint32_t dummy2;\r
108 uint32_t dummy3;\r
109\r
6d866bb7 110 SPUCHAN_orig s_chan[MAXCHAN]; \r
ef79bbde
P
111\r
112} SPUOSSFreeze_t;\r
113\r
114////////////////////////////////////////////////////////////////////////\r
115\r
116void LoadStateV5(SPUFreeze_t * pF); // newest version\r
117void LoadStateUnknown(SPUFreeze_t * pF); // unknown format\r
118\r
119extern int lastch;\r
120\r
6d866bb7 121// we want to retain compatibility between versions,\r
122// so use original channel struct\r
381ea103 123static void save_channel(SPUCHAN_orig *d, const SPUCHAN *s, int ch)\r
6d866bb7 124{\r
125 memset(d, 0, sizeof(*d));\r
126 d->bNew = !!(dwNewChannel & (1<<ch));\r
127 d->iSBPos = s->iSBPos;\r
128 d->spos = s->spos;\r
129 d->sinc = s->sinc;\r
130 memcpy(d->SB, s->SB, sizeof(d->SB));\r
7e44d49d 131 d->pStart = (unsigned char *)((regAreaGet(ch,6)&~1)<<3);\r
6d866bb7 132 d->pCurr = s->pCurr;\r
133 d->pLoop = s->pLoop;\r
134 d->bOn = !!(dwChannelOn & (1<<ch));\r
135 d->bStop = s->bStop;\r
136 d->bReverb = s->bReverb;\r
7e44d49d 137 d->iActFreq = 1;\r
138 d->iUsedFreq = 2;\r
6d866bb7 139 d->iLeftVolume = s->iLeftVolume;\r
7e44d49d 140 d->bIgnoreLoop = 0;\r
6d866bb7 141 d->iRightVolume = s->iRightVolume;\r
142 d->iRawPitch = s->iRawPitch;\r
381ea103 143 d->s_1 = s->SB[27]; // yes it's reversed\r
144 d->s_2 = s->SB[26];\r
6d866bb7 145 d->bRVBActive = s->bRVBActive;\r
6d866bb7 146 d->bNoise = s->bNoise;\r
147 d->bFMod = s->bFMod;\r
6d866bb7 148 d->ADSRX.State = s->ADSRX.State;\r
149 d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
150 d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
151 d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
152 d->ADSRX.SustainLevel = s->ADSRX.SustainLevel;\r
153 d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp;\r
154 d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease;\r
155 d->ADSRX.SustainRate = s->ADSRX.SustainRate;\r
156 d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp;\r
157 d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate;\r
158 d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol;\r
159 d->ADSRX.lVolume = d->bOn; // hmh\r
160}\r
161\r
381ea103 162static void load_channel(SPUCHAN *d, const SPUCHAN_orig *s, int ch)\r
6d866bb7 163{\r
164 memset(d, 0, sizeof(*d));\r
165 if (s->bNew) dwNewChannel |= 1<<ch;\r
166 d->iSBPos = s->iSBPos;\r
167 d->spos = s->spos;\r
168 d->sinc = s->sinc;\r
169 memcpy(d->SB, s->SB, sizeof(d->SB));\r
3fc2a4c2 170 d->pCurr = (void *)((long)s->pCurr & 0x7fff0);\r
171 d->pLoop = (void *)((long)s->pLoop & 0x7fff0);\r
6d866bb7 172 if (s->bOn) dwChannelOn |= 1<<ch;\r
173 d->bStop = s->bStop;\r
174 d->bReverb = s->bReverb;\r
6d866bb7 175 d->iLeftVolume = s->iLeftVolume;\r
6d866bb7 176 d->iRightVolume = s->iRightVolume;\r
177 d->iRawPitch = s->iRawPitch;\r
6d866bb7 178 d->bRVBActive = s->bRVBActive;\r
6d866bb7 179 d->bNoise = s->bNoise;\r
180 d->bFMod = s->bFMod;\r
6d866bb7 181 d->ADSRX.State = s->ADSRX.State;\r
182 d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
183 d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
184 d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
185 d->ADSRX.SustainLevel = s->ADSRX.SustainLevel;\r
186 d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp;\r
187 d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease;\r
188 d->ADSRX.SustainRate = s->ADSRX.SustainRate;\r
189 d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp;\r
190 d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate;\r
191 d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol;\r
192}\r
193\r
ef79bbde
P
194////////////////////////////////////////////////////////////////////////\r
195// SPUFREEZE: called by main emu on savestate load/save\r
196////////////////////////////////////////////////////////////////////////\r
197\r
198long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF)\r
199{\r
200 int i;SPUOSSFreeze_t * pFO;\r
201\r
202 if(!pF) return 0; // first check\r
203\r
204 if(ulFreezeMode) // info or save?\r
205 {//--------------------------------------------------//\r
206 if(ulFreezeMode==1) \r
207 memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t));\r
208\r
209 strcpy(pF->szSPUName,"PBOSS");\r
210 pF->ulFreezeVersion=5;\r
211 pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t);\r
212\r
213 if(ulFreezeMode==2) return 1; // info mode? ok, bye\r
214 // save mode:\r
215 RemoveTimer(); // stop timer\r
216\r
217 memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos\r
218 memcpy(pF->cSPUPort,regArea,0x200);\r
219\r
220 if(xapGlobal && XAPlay!=XAFeed) // some xa\r
221 {\r
222 pF->xaS=*xapGlobal; \r
223 }\r
224 else \r
225 memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa\r
226\r
227 pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff\r
228\r
229 pFO->spuIrq=spuIrq;\r
230 if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC;\r
231\r
232 pFO->spuAddr=spuAddr;\r
233 if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d;\r
234\r
3fc2a4c2 235 dwChannelOn&=~dwPendingChanOff;\r
236 dwPendingChanOff=0;\r
237\r
ef79bbde
P
238 for(i=0;i<MAXCHAN;i++)\r
239 {\r
6d866bb7 240 save_channel(&pFO->s_chan[i],&s_chan[i],i);\r
ef79bbde
P
241 if(pFO->s_chan[i].pCurr)\r
242 pFO->s_chan[i].pCurr-=(unsigned long)spuMemC;\r
243 if(pFO->s_chan[i].pLoop)\r
244 pFO->s_chan[i].pLoop-=(unsigned long)spuMemC;\r
245 }\r
246\r
247 SetupTimer(); // sound processing on again\r
248\r
249 return 1;\r
250 //--------------------------------------------------//\r
251 }\r
252 \r
253 if(ulFreezeMode!=0) return 0; // bad mode? bye\r
254\r
255 RemoveTimer(); // we stop processing while doing the save!\r
256\r
257 memcpy(spuMem,pF->cSPURam,0x80000); // get ram\r
258 memcpy(regArea,pF->cSPUPort,0x200);\r
259\r
260 if(pF->xaS.nsamples<=4032) // start xa again\r
261 SPUplayADPCMchannel(&pF->xaS);\r
262\r
263 xapGlobal=0;\r
3fc2a4c2 264 dwPendingChanOff=0;\r
ef79bbde
P
265\r
266 if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
267 LoadStateV5(pF);\r
268 else LoadStateUnknown(pF);\r
269\r
270 lastch = -1;\r
271\r
272 // repair some globals\r
273 for(i=0;i<=62;i+=2)\r
274 SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]);\r
275 SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]);\r
276 SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]);\r
277 SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]);\r
278\r
279 SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000));\r
280 SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]);\r
281 SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]);\r
282 SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]);\r
283\r
284 // fix to prevent new interpolations from crashing\r
285 for(i=0;i<MAXCHAN;i++) s_chan[i].SB[28]=0;\r
286\r
287 SetupTimer(); // start sound processing again\r
288\r
289 return 1;\r
290}\r
291\r
292////////////////////////////////////////////////////////////////////////\r
293\r
294void LoadStateV5(SPUFreeze_t * pF)\r
295{\r
296 int i;SPUOSSFreeze_t * pFO;\r
297\r
298 pFO=(SPUOSSFreeze_t *)(pF+1);\r
299\r
300 spuIrq = pFO->spuIrq;\r
3fc2a4c2 301 if(pFO->pSpuIrq) pSpuIrq = spuMemC+((long)pFO->pSpuIrq&0x7fff0); else pSpuIrq=NULL;\r
ef79bbde
P
302\r
303 if(pFO->spuAddr)\r
304 {\r
305 spuAddr = pFO->spuAddr;\r
306 if (spuAddr == 0xbaadf00d) spuAddr = 0;\r
307 }\r
308\r
6d866bb7 309 dwNewChannel=0;\r
310 dwChannelOn=0;\r
174c454a 311 dwChannelDead=0;\r
ef79bbde
P
312 for(i=0;i<MAXCHAN;i++)\r
313 {\r
6d866bb7 314 load_channel(&s_chan[i],&pFO->s_chan[i],i);\r
ef79bbde 315\r
ef79bbde
P
316 s_chan[i].pCurr+=(unsigned long)spuMemC;\r
317 s_chan[i].pLoop+=(unsigned long)spuMemC;\r
ef79bbde
P
318 }\r
319}\r
320\r
321////////////////////////////////////////////////////////////////////////\r
322\r
323void LoadStateUnknown(SPUFreeze_t * pF)\r
324{\r
325 int i;\r
326\r
327 for(i=0;i<MAXCHAN;i++)\r
328 {\r
ef79bbde 329 s_chan[i].bStop=0;\r
ef79bbde 330 s_chan[i].pLoop=spuMemC;\r
ef79bbde
P
331 }\r
332\r
333 dwNewChannel=0;\r
6d866bb7 334 dwChannelOn=0;\r
174c454a 335 dwChannelDead=0;\r
ef79bbde
P
336 pSpuIrq=0;\r
337\r
338 for(i=0;i<0xc0;i++)\r
339 {\r
340 SPUwriteRegister(0x1f801c00+i*2,regArea[i]);\r
341 }\r
342}\r
343\r
344////////////////////////////////////////////////////////////////////////\r