spu: rm bunch of unused functions
[pcsx_rearmed.git] / plugins / dfsound / registers.c
CommitLineData
ef79bbde
P
1/***************************************************************************\r
2 registers.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_REGISTERS\r
21\r
22#include "externals.h"\r
23#include "registers.h"\r
3154bfab 24#include "spu_config.h"\r
a4621d43 25#include "spu.h"\r
ef79bbde 26\r
7e44d49d 27static void SoundOn(int start,int end,unsigned short val);\r
28static void SoundOff(int start,int end,unsigned short val);\r
29static void FModOn(int start,int end,unsigned short val);\r
30static void NoiseOn(int start,int end,unsigned short val);\r
31static void SetVolumeL(unsigned char ch,short vol);\r
32static void SetVolumeR(unsigned char ch,short vol);\r
33static void SetPitch(int ch,unsigned short val);\r
34static void ReverbOn(int start,int end,unsigned short val);\r
35\r
ef79bbde
P
36////////////////////////////////////////////////////////////////////////\r
37// WRITE REGISTERS: called by main emu\r
38////////////////////////////////////////////////////////////////////////\r
39\r
4b22d950 40static const uint32_t ignore_dupe[16] = {\r
650adfd2 41 // ch 0-15 c40 c80 cc0\r
42 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,\r
43 // ch 16-24 d40 control reverb\r
4b22d950 44 0x7f7f7f7f, 0x7f7f7f7f, 0xff05ff0f, 0xffffffff,\r
45 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,\r
46 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff\r
650adfd2 47};\r
48\r
49void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,\r
50 unsigned int cycles)\r
ef79bbde 51{\r
4b22d950 52 int r = reg & 0xffe;\r
650adfd2 53 int rofs = (r - 0xc00) >> 1;\r
3154bfab 54 int changed = spu.regArea[rofs] != val;\r
55 spu.regArea[rofs] = val;\r
650adfd2 56\r
57 if (!changed && (ignore_dupe[rofs >> 5] & (1 << (rofs & 0x1f))))\r
58 return;\r
59 // zero keyon/keyoff?\r
60 if (val == 0 && (r & 0xff8) == 0xd88)\r
61 return;\r
62\r
63a4f6b6 63 do_samples_if_needed(cycles, 0);\r
ef79bbde
P
64\r
65 if(r>=0x0c00 && r<0x0d80) // some channel info?\r
66 {\r
67 int ch=(r>>4)-0xc0; // calc channel\r
68 switch(r&0x0f)\r
69 {\r
70 //------------------------------------------------// r volume\r
71 case 0: \r
72 SetVolumeL((unsigned char)ch,val);\r
73 break;\r
74 //------------------------------------------------// l volume\r
75 case 2: \r
76 SetVolumeR((unsigned char)ch,val);\r
77 break;\r
78 //------------------------------------------------// pitch\r
79 case 4: \r
80 SetPitch(ch,val);\r
650adfd2 81 goto upd_irq;\r
ef79bbde
P
82 //------------------------------------------------// start\r
83 case 6: \r
7e44d49d 84 // taken from regArea later\r
ef79bbde
P
85 break;\r
86 //------------------------------------------------// level with pre-calcs\r
87 case 8:\r
88 {\r
6d866bb7 89 const unsigned long lval=val;\r
ef79bbde 90 //---------------------------------------------//\r
5514a050 91 spu.s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;\r
92 spu.s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;\r
93 spu.s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;\r
94 spu.s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;\r
ef79bbde 95 //---------------------------------------------//\r
ef79bbde
P
96 }\r
97 break;\r
98 //------------------------------------------------// adsr times with pre-calcs\r
99 case 10:\r
100 {\r
6d866bb7 101 const unsigned long lval=val;\r
ef79bbde
P
102\r
103 //----------------------------------------------//\r
5514a050 104 spu.s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;\r
105 spu.s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;\r
106 spu.s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;\r
107 spu.s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;\r
108 spu.s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;\r
ef79bbde 109 //----------------------------------------------//\r
ef79bbde
P
110 }\r
111 break;\r
112 //------------------------------------------------// adsr volume... mmm have to investigate this\r
113 case 12:\r
114 break;\r
115 //------------------------------------------------//\r
116 case 14: // loop?\r
5514a050 117 spu.s_chan[ch].pLoop=spu.spuMemC+((val&~1)<<3);\r
16f3ca66 118 spu.s_chan[ch].bIgnoreLoop = 1;\r
650adfd2 119 goto upd_irq;\r
ef79bbde
P
120 //------------------------------------------------//\r
121 }\r
ef79bbde
P
122 return;\r
123 }\r
4b22d950 124 else if (0x0e00 <= r && r < 0x0e60)\r
125 {\r
126 int ch = (r >> 2) & 0x1f;\r
127 log_unhandled("c%02d w %cvol %04x\n", ch, (r & 2) ? 'r' : 'l', val);\r
128 spu.s_chan[ch].iVolume[(r >> 1) & 1] = (signed short)val >> 1;\r
129 }\r
ef79bbde
P
130\r
131 switch(r)\r
132 {\r
133 //-------------------------------------------------//\r
134 case H_SPUaddr:\r
3154bfab 135 spu.spuAddr = (unsigned long) val<<3;\r
ef79bbde
P
136 break;\r
137 //-------------------------------------------------//\r
138 case H_SPUdata:\r
a4621d43 139 *(unsigned short *)(spu.spuMemC + spu.spuAddr) = HTOLE16(val);\r
5514a050 140 spu.spuAddr += 2;\r
141 spu.spuAddr &= 0x7fffe;\r
ef79bbde
P
142 break;\r
143 //-------------------------------------------------//\r
144 case H_SPUctrl:\r
3154bfab 145 if (!(spu.spuCtrl & CTRL_IRQ)) {\r
146 spu.spuStat&=~STAT_IRQ;\r
650adfd2 147 if (val & CTRL_IRQ)\r
148 schedule_next_irq();\r
149 }\r
3154bfab 150 spu.spuCtrl=val;\r
ef79bbde
P
151 break;\r
152 //-------------------------------------------------//\r
153 case H_SPUstat:\r
3154bfab 154 spu.spuStat=val&0xf800;\r
ef79bbde
P
155 break;\r
156 //-------------------------------------------------//\r
157 case H_SPUReverbAddr:\r
650adfd2 158 goto rvbd;\r
ef79bbde
P
159 //-------------------------------------------------//\r
160 case H_SPUirqAddr:\r
a5ff8be2 161 //if (val & 1)\r
162 // log_unhandled("w irq with lsb: %08lx %04x\n", reg, val);\r
3154bfab 163 spu.pSpuIrq=spu.spuMemC+(((unsigned long) val<<3)&~0xf);\r
650adfd2 164 goto upd_irq;\r
ef79bbde
P
165 //-------------------------------------------------//\r
166 case H_SPUrvolL:\r
05c7cec7 167 spu.rvb->VolLeft=val;\r
ef79bbde
P
168 break;\r
169 //-------------------------------------------------//\r
170 case H_SPUrvolR:\r
05c7cec7 171 spu.rvb->VolRight=val;\r
ef79bbde
P
172 break;\r
173 //-------------------------------------------------//\r
174\r
6c9db47c 175 case H_SPUmvolL:\r
176 case H_SPUmvolR:\r
177 if (val & 0x8000)\r
178 log_unhandled("w master sweep: %08lx %04x\n", reg, val);\r
179 break;\r
180\r
181 case 0x0dac:\r
182 if (val != 4)\r
183 log_unhandled("1f801dac %04x\n", val);\r
184 break;\r
185\r
ef79bbde
P
186/*\r
187 case H_ExtLeft:\r
188 //auxprintf("EL %d\n",val);\r
189 break;\r
190 //-------------------------------------------------//\r
191 case H_ExtRight:\r
192 //auxprintf("ER %d\n",val);\r
193 break;\r
194 //-------------------------------------------------//\r
195 case H_SPUmvolL:\r
196 //auxprintf("ML %d\n",val);\r
197 break;\r
198 //-------------------------------------------------//\r
199 case H_SPUmvolR:\r
200 //auxprintf("MR %d\n",val);\r
201 break;\r
202 //-------------------------------------------------//\r
203 case H_SPUMute1:\r
204 //auxprintf("M0 %04x\n",val);\r
205 break;\r
206 //-------------------------------------------------//\r
207 case H_SPUMute2:\r
208 //auxprintf("M1 %04x\n",val);\r
209 break;\r
210*/\r
211 //-------------------------------------------------//\r
212 case H_SPUon1:\r
213 SoundOn(0,16,val);\r
214 break;\r
215 //-------------------------------------------------//\r
216 case H_SPUon2:\r
217 SoundOn(16,24,val);\r
218 break;\r
219 //-------------------------------------------------//\r
220 case H_SPUoff1:\r
221 SoundOff(0,16,val);\r
222 break;\r
223 //-------------------------------------------------//\r
224 case H_SPUoff2:\r
225 SoundOff(16,24,val);\r
226 break;\r
227 //-------------------------------------------------//\r
228 case H_CDLeft:\r
b64fb891 229 spu.iLeftXAVol=(int16_t)val;\r
230 if(spu.cddavCallback) spu.cddavCallback(0,(int16_t)val);\r
ef79bbde
P
231 break;\r
232 case H_CDRight:\r
b64fb891 233 spu.iRightXAVol=(int16_t)val;\r
234 if(spu.cddavCallback) spu.cddavCallback(1,(int16_t)val);\r
ef79bbde
P
235 break;\r
236 //-------------------------------------------------//\r
237 case H_FMod1:\r
238 FModOn(0,16,val);\r
239 break;\r
240 //-------------------------------------------------//\r
241 case H_FMod2:\r
242 FModOn(16,24,val);\r
243 break;\r
244 //-------------------------------------------------//\r
245 case H_Noise1:\r
246 NoiseOn(0,16,val);\r
247 break;\r
248 //-------------------------------------------------//\r
249 case H_Noise2:\r
250 NoiseOn(16,24,val);\r
251 break;\r
252 //-------------------------------------------------//\r
253 case H_RVBon1:\r
254 ReverbOn(0,16,val);\r
255 break;\r
256 //-------------------------------------------------//\r
257 case H_RVBon2:\r
258 ReverbOn(16,24,val);\r
259 break;\r
260 //-------------------------------------------------//\r
7b2c4897 261 case H_Reverb+0 : goto rvbd;\r
262 case H_Reverb+2 : goto rvbd;\r
263 case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; break;\r
264 case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; break;\r
265 case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; break;\r
266 case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; break;\r
267 case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; break;\r
268 case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; break;\r
269 case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; break;\r
270 case H_Reverb+18 : spu.rvb->FB_X=(short)val; break;\r
271 case H_Reverb+20 : goto rvbd;\r
272 case H_Reverb+22 : goto rvbd;\r
273 case H_Reverb+24 : goto rvbd;\r
274 case H_Reverb+26 : goto rvbd;\r
275 case H_Reverb+28 : goto rvbd;\r
276 case H_Reverb+30 : goto rvbd;\r
277 case H_Reverb+32 : goto rvbd;\r
278 case H_Reverb+34 : goto rvbd;\r
279 case H_Reverb+36 : goto rvbd;\r
280 case H_Reverb+38 : goto rvbd;\r
281 case H_Reverb+40 : goto rvbd;\r
282 case H_Reverb+42 : goto rvbd;\r
283 case H_Reverb+44 : goto rvbd;\r
284 case H_Reverb+46 : goto rvbd;\r
285 case H_Reverb+48 : goto rvbd;\r
286 case H_Reverb+50 : goto rvbd;\r
287 case H_Reverb+52 : goto rvbd;\r
288 case H_Reverb+54 : goto rvbd;\r
289 case H_Reverb+56 : goto rvbd;\r
290 case H_Reverb+58 : goto rvbd;\r
291 case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; break;\r
292 case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; break;\r
ef79bbde 293 }\r
650adfd2 294 return;\r
295\r
296upd_irq:\r
3154bfab 297 if (spu.spuCtrl & CTRL_IRQ)\r
650adfd2 298 schedule_next_irq();\r
299 return;\r
ef79bbde 300\r
650adfd2 301rvbd:\r
05c7cec7 302 spu.rvb->dirty = 1; // recalculate on next update\r
ef79bbde
P
303}\r
304\r
305////////////////////////////////////////////////////////////////////////\r
306// READ REGISTER: called by main emu\r
307////////////////////////////////////////////////////////////////////////\r
308\r
309unsigned short CALLBACK SPUreadRegister(unsigned long reg)\r
310{\r
4b22d950 311 const unsigned long r = reg & 0xffe;\r
ef79bbde 312 \r
ef79bbde
P
313 if(r>=0x0c00 && r<0x0d80)\r
314 {\r
315 switch(r&0x0f)\r
316 {\r
317 case 12: // get adsr vol\r
318 {\r
319 const int ch=(r>>4)-0xc0;\r
3154bfab 320 if(spu.dwNewChannel&(1<<ch)) return 1; // we are started, but not processed? return 1\r
5aa94fa0 321 if((spu.dwChannelsAudible&(1<<ch)) && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well\r
5514a050 322 !spu.s_chan[ch].ADSRX.EnvelopeVol)\r
ef79bbde 323 return 1;\r
5514a050 324 return (unsigned short)(spu.s_chan[ch].ADSRX.EnvelopeVol>>16);\r
ef79bbde
P
325 }\r
326\r
327 case 14: // get loop address\r
328 {\r
329 const int ch=(r>>4)-0xc0;\r
5514a050 330 return (unsigned short)((spu.s_chan[ch].pLoop-spu.spuMemC)>>3);\r
ef79bbde
P
331 }\r
332 }\r
333 }\r
4b22d950 334 else if (0x0e00 <= r && r < 0x0e60)\r
335 {\r
336 int ch = (r >> 2) & 0x1f;\r
337 int v = spu.s_chan[ch].iVolume[(r >> 1) & 1] << 1;\r
338 log_unhandled("c%02d r %cvol %04x\n", ch, (r & 2) ? 'r' : 'l', v);\r
339 return v;\r
340 }\r
ef79bbde
P
341\r
342 switch(r)\r
343 {\r
344 case H_SPUctrl:\r
3154bfab 345 return spu.spuCtrl;\r
ef79bbde
P
346\r
347 case H_SPUstat:\r
d056f51b 348 return (spu.spuStat & ~0x3F) | (spu.spuCtrl & 0x3F);\r
ef79bbde
P
349 \r
350 case H_SPUaddr:\r
3154bfab 351 return (unsigned short)(spu.spuAddr>>3);\r
ef79bbde
P
352\r
353 case H_SPUdata:\r
354 {\r
a4621d43 355 unsigned short s = LE16TOH(*(unsigned short *)(spu.spuMemC + spu.spuAddr));\r
5514a050 356 spu.spuAddr += 2;\r
357 spu.spuAddr &= 0x7fffe;\r
ef79bbde
P
358 return s;\r
359 }\r
360\r
ef79bbde
P
361 //case H_SPUIsOn1:\r
362 // return IsSoundOn(0,16);\r
363\r
364 //case H_SPUIsOn2:\r
365 // return IsSoundOn(16,24);\r
366 \r
6c9db47c 367 case H_SPUMute1:\r
368 case H_SPUMute2:\r
369 log_unhandled("r isOn: %08lx\n", reg);\r
370 break;\r
906b1599 371\r
372 case 0x0dac:\r
373 case H_SPUirqAddr:\r
374 case H_CDLeft:\r
375 case H_CDRight:\r
376 case H_ExtLeft:\r
377 case H_ExtRight:\r
378 break;\r
379\r
380 default:\r
381 if (r >= 0xda0)\r
382 log_unhandled("spu r %08lx\n", reg);\r
383 break;\r
ef79bbde
P
384 }\r
385\r
3154bfab 386 return spu.regArea[(r-0xc00)>>1];\r
ef79bbde
P
387}\r
388 \r
389////////////////////////////////////////////////////////////////////////\r
390// SOUND ON register write\r
391////////////////////////////////////////////////////////////////////////\r
392\r
7e44d49d 393static void SoundOn(int start,int end,unsigned short val)\r
ef79bbde
P
394{\r
395 int ch;\r
396\r
397 for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
398 {\r
5fdcf5cd 399 if((val&1) && regAreaGetCh(ch, 6)) // mmm... start has to be set before key on !?!\r
ef79bbde 400 {\r
16f3ca66 401 spu.s_chan[ch].bIgnoreLoop = 0;\r
3154bfab 402 spu.dwNewChannel|=(1<<ch);\r
ef79bbde
P
403 }\r
404 }\r
405}\r
406\r
407////////////////////////////////////////////////////////////////////////\r
408// SOUND OFF register write\r
409////////////////////////////////////////////////////////////////////////\r
410\r
7e44d49d 411static void SoundOff(int start,int end,unsigned short val)\r
ef79bbde
P
412{\r
413 int ch;\r
414 for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
415 {\r
9ad8abfa 416 if(val&1)\r
ef79bbde 417 {\r
5514a050 418 spu.s_chan[ch].ADSRX.State = ADSR_RELEASE;\r
b00afb77 419\r
420 // Jungle Book - Rhythm 'n Groove\r
421 // - turns off buzzing sound (loop hangs)\r
3154bfab 422 spu.dwNewChannel &= ~(1<<ch);\r
ef79bbde
P
423 } \r
424 }\r
425}\r
426\r
427////////////////////////////////////////////////////////////////////////\r
428// FMOD register write\r
429////////////////////////////////////////////////////////////////////////\r
430\r
7e44d49d 431static void FModOn(int start,int end,unsigned short val)\r
ef79bbde
P
432{\r
433 int ch;\r
434\r
435 for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
436 {\r
437 if(val&1) // -> fmod on/off\r
438 {\r
439 if(ch>0) \r
440 {\r
5514a050 441 spu.s_chan[ch].bFMod=1; // --> sound channel\r
442 spu.s_chan[ch-1].bFMod=2; // --> freq channel\r
ef79bbde
P
443 }\r
444 }\r
445 else\r
446 {\r
5514a050 447 spu.s_chan[ch].bFMod=0; // --> turn off fmod\r
448 if(ch>0&&spu.s_chan[ch-1].bFMod==2)\r
449 spu.s_chan[ch-1].bFMod=0;\r
ef79bbde
P
450 }\r
451 }\r
452}\r
453\r
454////////////////////////////////////////////////////////////////////////\r
455// NOISE register write\r
456////////////////////////////////////////////////////////////////////////\r
457\r
7e44d49d 458static void NoiseOn(int start,int end,unsigned short val)\r
ef79bbde
P
459{\r
460 int ch;\r
461\r
462 for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
463 {\r
5514a050 464 spu.s_chan[ch].bNoise=val&1; // -> noise on/off\r
ef79bbde
P
465 }\r
466}\r
467\r
468////////////////////////////////////////////////////////////////////////\r
469// LEFT VOLUME register write\r
470////////////////////////////////////////////////////////////////////////\r
471\r
472// please note: sweep and phase invert are wrong... but I've never seen\r
473// them used\r
474\r
7e44d49d 475static void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME\r
ef79bbde 476{\r
ef79bbde
P
477 if(vol&0x8000) // sweep?\r
478 {\r
479 short sInc=1; // -> sweep up?\r
6c9db47c 480 log_unhandled("ch%d sweepl %04x\n", ch, vol);\r
ef79bbde
P
481 if(vol&0x2000) sInc=-1; // -> or down?\r
482 if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this\r
483 vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64\r
484 vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!\r
485 vol*=128;\r
486 }\r
487 else // no sweep:\r
488 {\r
489 if(vol&0x4000) // -> mmm... phase inverted? have to investigate this\r
490 //vol^=0xffff;\r
491 vol=0x3fff-(vol&0x3fff);\r
492 }\r
493\r
494 vol&=0x3fff;\r
5514a050 495 spu.s_chan[ch].iLeftVolume=vol; // store volume\r
4b22d950 496 //spu.regArea[(0xe00-0xc00)/2 + ch*2 + 0] = vol << 1;\r
ef79bbde
P
497}\r
498\r
499////////////////////////////////////////////////////////////////////////\r
500// RIGHT VOLUME register write\r
501////////////////////////////////////////////////////////////////////////\r
502\r
7e44d49d 503static void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME\r
ef79bbde 504{\r
ef79bbde
P
505 if(vol&0x8000) // comments... see above :)\r
506 {\r
507 short sInc=1;\r
6c9db47c 508 log_unhandled("ch%d sweepr %04x\n", ch, vol);\r
ef79bbde
P
509 if(vol&0x2000) sInc=-1;\r
510 if(vol&0x1000) vol^=0xffff;\r
511 vol=((vol&0x7f)+1)/2; \r
512 vol+=vol/(2*sInc);\r
513 vol*=128;\r
514 }\r
515 else \r
516 {\r
517 if(vol&0x4000) //vol=vol^=0xffff;\r
518 vol=0x3fff-(vol&0x3fff);\r
519 }\r
520\r
521 vol&=0x3fff;\r
522\r
5514a050 523 spu.s_chan[ch].iRightVolume=vol;\r
4b22d950 524 //spu.regArea[(0xe00-0xc00)/2 + ch*2 + 1] = vol << 1;\r
ef79bbde
P
525}\r
526\r
527////////////////////////////////////////////////////////////////////////\r
528// PITCH register write\r
529////////////////////////////////////////////////////////////////////////\r
530\r
7e44d49d 531static void SetPitch(int ch,unsigned short val) // SET PITCH\r
ef79bbde
P
532{\r
533 int NP;\r
534 if(val>0x3fff) NP=0x3fff; // get pitch val\r
535 else NP=val;\r
536\r
f3fa20c2 537 spu.s_chan[ch].iRawPitch = NP;\r
538 spu.s_chan[ch].sinc = NP << 4;\r
539 spu.s_chan[ch].sinc_inv = 0;\r
53d4b74d 540 spu.s_chan[ch].bNewPitch = 1;\r
1d5d35bc 541\r
542 // don't mess spu.dwChannelsAudible as adsr runs independently\r
ef79bbde
P
543}\r
544\r
545////////////////////////////////////////////////////////////////////////\r
546// REVERB register write\r
547////////////////////////////////////////////////////////////////////////\r
548\r
7e44d49d 549static void ReverbOn(int start,int end,unsigned short val)\r
ef79bbde
P
550{\r
551 int ch;\r
552\r
553 for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
554 {\r
5514a050 555 spu.s_chan[ch].bReverb=val&1; // -> reverb on/off\r
ef79bbde
P
556 }\r
557}\r