add basic .Z support
[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
25#include "regs.h"\r
26\r
27////////////////////////////////////////////////////////////////////////\r
28// freeze structs\r
29////////////////////////////////////////////////////////////////////////\r
30\r
31typedef struct\r
32{\r
33 char szSPUName[8];\r
34 uint32_t ulFreezeVersion;\r
35 uint32_t ulFreezeSize;\r
36 unsigned char cSPUPort[0x200];\r
37 unsigned char cSPURam[0x80000];\r
38 xa_decode_t xaS; \r
39} SPUFreeze_t;\r
40\r
41typedef struct\r
42{\r
43 unsigned short spuIrq;\r
44 uint32_t pSpuIrq;\r
45 uint32_t spuAddr;\r
46 uint32_t dummy1;\r
47 uint32_t dummy2;\r
48 uint32_t dummy3;\r
49\r
50 SPUCHAN s_chan[MAXCHAN]; \r
51\r
52} SPUOSSFreeze_t;\r
53\r
54////////////////////////////////////////////////////////////////////////\r
55\r
56void LoadStateV5(SPUFreeze_t * pF); // newest version\r
57void LoadStateUnknown(SPUFreeze_t * pF); // unknown format\r
58\r
59extern int lastch;\r
60\r
61////////////////////////////////////////////////////////////////////////\r
62// SPUFREEZE: called by main emu on savestate load/save\r
63////////////////////////////////////////////////////////////////////////\r
64\r
65long CALLBACK SPUfreeze(uint32_t ulFreezeMode,SPUFreeze_t * pF)\r
66{\r
67 int i;SPUOSSFreeze_t * pFO;\r
68\r
69 if(!pF) return 0; // first check\r
70\r
71 if(ulFreezeMode) // info or save?\r
72 {//--------------------------------------------------//\r
73 if(ulFreezeMode==1) \r
74 memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t));\r
75\r
76 strcpy(pF->szSPUName,"PBOSS");\r
77 pF->ulFreezeVersion=5;\r
78 pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t);\r
79\r
80 if(ulFreezeMode==2) return 1; // info mode? ok, bye\r
81 // save mode:\r
82 RemoveTimer(); // stop timer\r
83\r
84 memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos\r
85 memcpy(pF->cSPUPort,regArea,0x200);\r
86\r
87 if(xapGlobal && XAPlay!=XAFeed) // some xa\r
88 {\r
89 pF->xaS=*xapGlobal; \r
90 }\r
91 else \r
92 memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa\r
93\r
94 pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff\r
95\r
96 pFO->spuIrq=spuIrq;\r
97 if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC;\r
98\r
99 pFO->spuAddr=spuAddr;\r
100 if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d;\r
101\r
102 for(i=0;i<MAXCHAN;i++)\r
103 {\r
104 memcpy((void *)&pFO->s_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN));\r
105 if(pFO->s_chan[i].pStart)\r
106 pFO->s_chan[i].pStart-=(unsigned long)spuMemC;\r
107 if(pFO->s_chan[i].pCurr)\r
108 pFO->s_chan[i].pCurr-=(unsigned long)spuMemC;\r
109 if(pFO->s_chan[i].pLoop)\r
110 pFO->s_chan[i].pLoop-=(unsigned long)spuMemC;\r
111 }\r
112\r
113 SetupTimer(); // sound processing on again\r
114\r
115 return 1;\r
116 //--------------------------------------------------//\r
117 }\r
118 \r
119 if(ulFreezeMode!=0) return 0; // bad mode? bye\r
120\r
121 RemoveTimer(); // we stop processing while doing the save!\r
122\r
123 memcpy(spuMem,pF->cSPURam,0x80000); // get ram\r
124 memcpy(regArea,pF->cSPUPort,0x200);\r
125\r
126 if(pF->xaS.nsamples<=4032) // start xa again\r
127 SPUplayADPCMchannel(&pF->xaS);\r
128\r
129 xapGlobal=0;\r
130\r
131 if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
132 LoadStateV5(pF);\r
133 else LoadStateUnknown(pF);\r
134\r
135 lastch = -1;\r
136\r
137 // repair some globals\r
138 for(i=0;i<=62;i+=2)\r
139 SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]);\r
140 SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]);\r
141 SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]);\r
142 SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]);\r
143\r
144 SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000));\r
145 SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]);\r
146 SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]);\r
147 SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]);\r
148\r
149 // fix to prevent new interpolations from crashing\r
150 for(i=0;i<MAXCHAN;i++) s_chan[i].SB[28]=0;\r
151\r
152 SetupTimer(); // start sound processing again\r
153\r
154 return 1;\r
155}\r
156\r
157////////////////////////////////////////////////////////////////////////\r
158\r
159void LoadStateV5(SPUFreeze_t * pF)\r
160{\r
161 int i;SPUOSSFreeze_t * pFO;\r
162\r
163 pFO=(SPUOSSFreeze_t *)(pF+1);\r
164\r
165 spuIrq = pFO->spuIrq;\r
166 if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=NULL;\r
167\r
168 if(pFO->spuAddr)\r
169 {\r
170 spuAddr = pFO->spuAddr;\r
171 if (spuAddr == 0xbaadf00d) spuAddr = 0;\r
172 }\r
173\r
174 for(i=0;i<MAXCHAN;i++)\r
175 {\r
176 memcpy((void *)&s_chan[i],(void *)&pFO->s_chan[i],sizeof(SPUCHAN));\r
177\r
178 s_chan[i].pStart+=(unsigned long)spuMemC;\r
179 s_chan[i].pCurr+=(unsigned long)spuMemC;\r
180 s_chan[i].pLoop+=(unsigned long)spuMemC;\r
181 s_chan[i].iMute=0;\r
182 s_chan[i].iIrqDone=0;\r
183 }\r
184}\r
185\r
186////////////////////////////////////////////////////////////////////////\r
187\r
188void LoadStateUnknown(SPUFreeze_t * pF)\r
189{\r
190 int i;\r
191\r
192 for(i=0;i<MAXCHAN;i++)\r
193 {\r
194 s_chan[i].bOn=0;\r
195 s_chan[i].bNew=0;\r
196 s_chan[i].bStop=0;\r
197 s_chan[i].ADSR.lVolume=0;\r
198 s_chan[i].pLoop=spuMemC;\r
199 s_chan[i].pStart=spuMemC;\r
200 s_chan[i].pLoop=spuMemC;\r
201 s_chan[i].iMute=0;\r
202 s_chan[i].iIrqDone=0;\r
203 }\r
204\r
205 dwNewChannel=0;\r
206 pSpuIrq=0;\r
207\r
208 for(i=0;i<0xc0;i++)\r
209 {\r
210 SPUwriteRegister(0x1f801c00+i*2,regArea[i]);\r
211 }\r
212}\r
213\r
214////////////////////////////////////////////////////////////////////////\r