1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "engines/engine.h"
24 #include "scumm/players/player_v2a.h"
25 #include "scumm/scumm.h"
26
27 namespace Scumm {
28
29 #define BASE_FREQUENCY 3579545
30
31 static uint32 CRCtable[256];
32
33
InitCRC()34 static void InitCRC() {
35 const uint32 poly = 0xEDB88320;
36 int i, j;
37 uint32 n;
38
39 for (i = 0; i < 256; i++) {
40 n = i;
41 for (j = 0; j < 8; j++)
42 n = (n & 1) ? ((n >> 1) ^ poly) : (n >> 1);
43 CRCtable[i] = n;
44 }
45 }
46
GetCRC(byte * data,int len)47 static uint32 GetCRC(byte *data, int len) {
48 uint32 CRC = 0xFFFFFFFF;
49 int i;
50 for (i = 0; i < len; i++)
51 CRC = (CRC >> 8) ^ CRCtable[(CRC ^ data[i]) & 0xFF];
52 return CRC ^ 0xFFFFFFFF;
53 }
54
55 class V2A_Sound {
56 public:
V2A_Sound()57 V2A_Sound() : _id(0), _mod(NULL) { }
~V2A_Sound()58 virtual ~V2A_Sound() {}
59 virtual void start(Player_MOD *mod, int id, const byte *data) = 0;
60 virtual bool update() = 0;
61 virtual void stop() = 0;
62 protected:
63 int _id;
64 Player_MOD *_mod;
65 };
66
67 // unsupported sound effect, print warning message to console
68 class V2A_Sound_Unsupported : public V2A_Sound {
69 public:
V2A_Sound_Unsupported()70 V2A_Sound_Unsupported() { }
start(Player_MOD * mod,int id,const byte * data)71 virtual void start(Player_MOD *mod, int id, const byte *data) {
72 warning("player_v2a - sound %i not supported", id);
73 }
update()74 virtual bool update() { return false; }
stop()75 virtual void stop() { }
76 };
77
78 // template, automatically stops all channels when a sound is silenced
79 template<int numChan>
80 class V2A_Sound_Base : public V2A_Sound {
81 public:
V2A_Sound_Base()82 V2A_Sound_Base() : _offset(0), _size(0), _data(0) { }
V2A_Sound_Base(uint16 offset,uint16 size)83 V2A_Sound_Base(uint16 offset, uint16 size) : _offset(offset), _size(size), _data(0) { }
stop()84 virtual void stop() {
85 assert(_id);
86 for (int i = 0; i < numChan; i++)
87 _mod->stopChannel(_id | (i << 8));
88 _id = 0;
89 free(_data);
90 _data = 0;
91 }
92 protected:
93 const uint16 _offset;
94 const uint16 _size;
95
96 char *_data;
97 };
98
99 // plays a music track
100 class V2A_Sound_Music : public V2A_Sound {
101 public:
V2A_Sound_Music(uint16 instoff,uint16 voloff,uint16 chan1off,uint16 chan2off,uint16 chan3off,uint16 chan4off,uint16 sampoff,bool looped)102 V2A_Sound_Music(uint16 instoff, uint16 voloff, uint16 chan1off, uint16 chan2off, uint16 chan3off, uint16 chan4off, uint16 sampoff, bool looped) :
103 _instoff(instoff), _voloff(voloff), _chan1off(chan1off), _chan2off(chan2off), _chan3off(chan3off), _chan4off(chan4off), _sampoff(sampoff), _looped(looped) { }
start(Player_MOD * mod,int id,const byte * data)104 virtual void start(Player_MOD *mod, int id, const byte *data) {
105 _mod = mod;
106 _id = id;
107
108 _data = (char *)malloc(READ_LE_UINT16(data));
109 memcpy(_data, data, READ_LE_UINT16(data));
110
111 _chan[0].dataptr_i = _chan1off;
112 _chan[1].dataptr_i = _chan2off;
113 _chan[2].dataptr_i = _chan3off;
114 _chan[3].dataptr_i = _chan4off;
115 for (int i = 0; i < 4; i++) {
116 _chan[i].dataptr = _chan[i].dataptr_i;
117 _chan[i].volbase = 0;
118 _chan[i].volptr = 0;
119 _chan[i].chan = 0;
120 _chan[i].dur = 0;
121 _chan[i].ticks = 0;
122 }
123 update();
124 }
update()125 virtual bool update() {
126 assert(_id);
127 int i, j = 0;
128 for (i = 0; i < 4; i++) {
129 if (_chan[i].dur) {
130 if (!--_chan[i].dur) {
131 _mod->stopChannel(_id | (_chan[i].chan << 8));
132 } else {
133 _mod->setChannelVol(_id | (_chan[i].chan << 8),
134 READ_BE_UINT16(_data + _chan[i].volbase + (_chan[i].volptr++ << 1)));
135 if (_chan[i].volptr == 0) {
136 _mod->stopChannel(_id | (_chan[i].chan << 8));
137 _chan[i].dur = 0;
138 }
139 }
140 }
141 if (!_chan[i].dataptr) {
142 j++;
143 continue;
144 }
145 if (READ_BE_UINT16(_data + _chan[i].dataptr) <= _chan[i].ticks) {
146 if (READ_BE_UINT16(_data + _chan[i].dataptr + 2) == 0xFFFF) {
147 if (_looped) {
148 _chan[i].dataptr = _chan[i].dataptr_i;
149 _chan[i].ticks = 0;
150 if (READ_BE_UINT16(_data + _chan[i].dataptr) > 0) {
151 _chan[i].ticks++;
152 continue;
153 }
154 } else {
155 _chan[i].dataptr = 0;
156 j++;
157 continue;
158 }
159 }
160 int freq = BASE_FREQUENCY / READ_BE_UINT16(_data + _chan[i].dataptr + 2);
161 int inst = READ_BE_UINT16(_data + _chan[i].dataptr + 8);
162 _chan[i].volbase = _voloff + (READ_BE_UINT16(_data + _instoff + (inst << 5)) << 9);
163 _chan[i].volptr = 0;
164 _chan[i].chan = READ_BE_UINT16(_data + _chan[i].dataptr + 6) & 0x3;
165
166 if (_chan[i].dur) // if there's something playing, stop it
167 _mod->stopChannel(_id | (_chan[i].chan << 8));
168
169 _chan[i].dur = READ_BE_UINT16(_data + _chan[i].dataptr + 4);
170
171 int vol = READ_BE_UINT16(_data + _chan[i].volbase + (_chan[i].volptr++ << 1));
172
173 int pan;
174 if ((_chan[i].chan == 0) || (_chan[i].chan == 3))
175 pan = -127;
176 else
177 pan = 127;
178 int offset = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x14);
179 int len = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x18);
180 int loopoffset = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x16);
181 int looplen = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x10);
182
183 int size = len + looplen;
184 char *data = (char *)malloc(size);
185 memcpy(data, _data + _sampoff + offset, len);
186 memcpy(data + len, _data + _sampoff + loopoffset, looplen);
187
188 _mod->startChannel(_id | (_chan[i].chan << 8), data, size, freq, vol, len, looplen + len, pan);
189 _chan[i].dataptr += 16;
190 }
191 _chan[i].ticks++;
192 }
193 if (j == 4)
194 return false;
195 return true;
196 }
stop()197 virtual void stop() {
198 assert(_id);
199 for (int i = 0; i < 4; i++) {
200 if (_chan[i].dur)
201 _mod->stopChannel(_id | (_chan[i].chan << 8));
202 }
203 free(_data);
204 _id = 0;
205 }
206 private:
207 const uint16 _instoff;
208 const uint16 _voloff;
209 const uint16 _chan1off;
210 const uint16 _chan2off;
211 const uint16 _chan3off;
212 const uint16 _chan4off;
213 const uint16 _sampoff;
214 const bool _looped;
215
216 char *_data;
217 struct tchan {
218 uint16 dataptr_i;
219 uint16 dataptr;
220 uint16 volbase;
221 uint8 volptr;
222 uint16 chan;
223 uint16 dur;
224 uint16 ticks;
225 } _chan[4];
226 };
227
228 // plays a single waveform
229 class V2A_Sound_Single : public V2A_Sound_Base<1> {
230 public:
V2A_Sound_Single(uint16 offset,uint16 size,uint16 freq,uint8 vol)231 V2A_Sound_Single(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
232 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)233 virtual void start(Player_MOD *mod, int id, const byte *data) {
234 _mod = mod;
235 _id = id;
236 char *tmp_data = (char *)malloc(_size);
237 memcpy(tmp_data, data + _offset, _size);
238 int vol = (_vol << 2) | (_vol >> 4);
239 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, vol, 0, 0);
240 _ticks = 1 + (60 * _size * _freq) / BASE_FREQUENCY;
241 }
update()242 virtual bool update() {
243 assert(_id);
244 _ticks--;
245 if (!_ticks) {
246 return false;
247 }
248 return true;
249 }
250 private:
251 const uint16 _freq;
252 const uint8 _vol;
253
254 int _ticks;
255 };
256
257 // plays a single looped waveform
258 class V2A_Sound_SingleLooped : public V2A_Sound_Base<1> {
259 public:
V2A_Sound_SingleLooped(uint16 offset,uint16 size,uint16 freq,uint8 vol,uint16 loopoffset,uint16 loopsize)260 V2A_Sound_SingleLooped(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint16 loopoffset, uint16 loopsize) :
261 V2A_Sound_Base<1>(offset, size), _loopoffset(loopoffset), _loopsize(loopsize), _freq(freq), _vol(vol) { }
V2A_Sound_SingleLooped(uint16 offset,uint16 size,uint16 freq,uint8 vol)262 V2A_Sound_SingleLooped(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
263 V2A_Sound_Base<1>(offset, size), _loopoffset(0), _loopsize(size), _freq(freq), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)264 virtual void start(Player_MOD *mod, int id, const byte *data) {
265 _mod = mod;
266 _id = id;
267 char *tmp_data = (char *)malloc(_size);
268 memcpy(tmp_data, data + _offset, _size);
269 int vol = (_vol << 2) | (_vol >> 4);
270 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, vol, _loopoffset, _loopoffset + _loopsize);
271 }
update()272 virtual bool update() {
273 assert(_id);
274 return true;
275 }
276 private:
277 const uint16 _loopoffset;
278 const uint16 _loopsize;
279 const uint16 _freq;
280 const uint8 _vol;
281 };
282
283 // plays two looped waveforms
284 class V2A_Sound_MultiLooped : public V2A_Sound_Base<2> {
285 public:
V2A_Sound_MultiLooped(uint16 offset,uint16 size,uint16 freq1,uint8 vol1,uint16 freq2,uint8 vol2)286 V2A_Sound_MultiLooped(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2) :
287 V2A_Sound_Base<2>(offset, size), _freq1(freq1), _vol1(vol1), _freq2(freq2), _vol2(vol2) { }
start(Player_MOD * mod,int id,const byte * data)288 virtual void start(Player_MOD *mod, int id, const byte *data) {
289 _mod = mod;
290 _id = id;
291 char *tmp_data1 = (char *)malloc(_size);
292 char *tmp_data2 = (char *)malloc(_size);
293 memcpy(tmp_data1, data + _offset, _size);
294 memcpy(tmp_data2, data + _offset, _size);
295 int vol1 = (_vol1 << 1) | (_vol1 >> 5);
296 int vol2 = (_vol2 << 1) | (_vol2 >> 5);
297 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, vol1, 0, _size, -127);
298 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, vol2, 0, _size, 127);
299 }
update()300 virtual bool update() {
301 assert(_id);
302 return true;
303 }
304 private:
305 const uint16 _freq1;
306 const uint8 _vol1;
307 const uint16 _freq2;
308 const uint8 _vol2;
309 };
310
311 // plays two looped waveforms for a fixed number of frames
312 class V2A_Sound_MultiLoopedDuration : public V2A_Sound_MultiLooped {
313 public:
V2A_Sound_MultiLoopedDuration(uint16 offset,uint16 size,uint16 freq1,uint8 vol1,uint16 freq2,uint8 vol2,uint16 numframes)314 V2A_Sound_MultiLoopedDuration(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2, uint16 numframes) :
315 V2A_Sound_MultiLooped(offset, size, freq1, vol1, freq2, vol2), _duration(numframes) { }
start(Player_MOD * mod,int id,const byte * data)316 virtual void start(Player_MOD *mod, int id, const byte *data) {
317 V2A_Sound_MultiLooped::start(mod, id, data);
318 _ticks = 0;
319 }
update()320 virtual bool update() {
321 assert(_id);
322 _ticks++;
323 if (_ticks >= _duration)
324 return false;
325 return true;
326 }
327 private:
328 const uint16 _duration;
329
330 int _ticks;
331 };
332
333 // plays a single looped waveform which starts at one frequency and bends to another frequency, where it remains until stopped
334 class V2A_Sound_SingleLoopedPitchbend : public V2A_Sound_Base<1> {
335 public:
V2A_Sound_SingleLoopedPitchbend(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint8 vol,uint8 step)336 V2A_Sound_SingleLoopedPitchbend(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol, uint8 step) :
337 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _vol(vol), _step(step) { }
start(Player_MOD * mod,int id,const byte * data)338 virtual void start(Player_MOD *mod, int id, const byte *data) {
339 _mod = mod;
340 _id = id;
341 char *tmp_data = (char *)malloc(_size);
342 memcpy(tmp_data, data + _offset, _size);
343 int vol = (_vol << 2) | (_vol >> 4);
344 _curfreq = _freq1;
345 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, vol, 0, _size);
346 }
update()347 virtual bool update() {
348 assert(_id);
349 if (_freq1 < _freq2) {
350 _curfreq += _step;
351 if (_curfreq > _freq2)
352 _curfreq = _freq2;
353 else
354 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
355 } else {
356 _curfreq -= _step;
357 if (_curfreq < _freq2)
358 _curfreq = _freq2;
359 else
360 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
361 }
362 return true;
363 }
364 private:
365 const uint16 _freq1;
366 const uint16 _freq2;
367 const uint8 _vol;
368 const uint16 _step;
369
370 uint16 _curfreq;
371 };
372
373 // plays a single looped waveform starting at a specific frequency/volume, dropping in frequency and fading volume to zero
374 // used when Maniac Mansion explodes
375 class V2A_Sound_Special_Maniac69 : public V2A_Sound_Base<1> {
376 public:
V2A_Sound_Special_Maniac69(uint16 offset,uint16 size,uint16 freq,uint8 vol)377 V2A_Sound_Special_Maniac69(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
378 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)379 virtual void start(Player_MOD *mod, int id, const byte *data) {
380 _mod = mod;
381 _id = id;
382 char *tmp_data = (char *)malloc(_size);
383 memcpy(tmp_data, data + _offset, _size);
384 _curvol = (_vol << 3) | (_vol >> 3);
385 _curfreq = _freq;
386 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, _curvol >> 1, 0, _size);
387 }
update()388 virtual bool update() {
389 assert(_id);
390 _curfreq += 2;
391 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
392 _curvol--;
393 if (_curvol == 0)
394 return false;
395 _mod->setChannelVol(_id, _curvol >> 1);
396 return true;
397 }
398 private:
399 const uint16 _freq;
400 const uint8 _vol;
401
402 uint16 _curfreq;
403 uint16 _curvol;
404 };
405
406 // plays a single looped waveform, fading the volume from zero to maximum at one rate, then back to zero at another rate
407 // used when a microwave oven goes 'Ding'
408 class V2A_Sound_Special_ManiacDing : public V2A_Sound_Base<1> {
409 public:
V2A_Sound_Special_ManiacDing(uint16 offset,uint16 size,uint16 freq,uint8 fadeinrate,uint8 fadeoutrate)410 V2A_Sound_Special_ManiacDing(uint16 offset, uint16 size, uint16 freq, uint8 fadeinrate, uint8 fadeoutrate) :
411 V2A_Sound_Base<1>(offset, size), _freq(freq), _fade1(fadeinrate), _fade2(fadeoutrate) { }
start(Player_MOD * mod,int id,const byte * data)412 virtual void start(Player_MOD *mod, int id, const byte *data) {
413 _mod = mod;
414 _id = id;
415 char *tmp_data = (char *)malloc(_size);
416 memcpy(tmp_data, data + _offset, _size);
417 _curvol = 1;
418 _dir = 0;
419 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, _curvol, 0, _size);
420 }
update()421 virtual bool update() {
422 assert(_id);
423 if (_dir == 0) {
424 _curvol += _fade1;
425 if (_curvol > 0x3F) {
426 _curvol = 0x3F;
427 _dir = 1;
428 }
429 } else {
430 _curvol -= _fade2;
431 if (_curvol < 1)
432 return false;
433 }
434 _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
435 return true;
436 }
437 private:
438 const uint16 _freq;
439 const uint16 _fade1;
440 const uint16 _fade2;
441
442 int _curvol;
443 int _dir;
444 };
445
446 // plays two looped waveforms, fading the volume from zero to maximum at one rate, then back to zero at another rate
447 // used in Zak McKracken for several stereo 'Ding' sounds
448 class V2A_Sound_Special_ZakStereoDing : public V2A_Sound_Base<2> {
449 public:
V2A_Sound_Special_ZakStereoDing(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint8 fadeinrate,uint8 fadeoutrate)450 V2A_Sound_Special_ZakStereoDing(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 fadeinrate, uint8 fadeoutrate) :
451 V2A_Sound_Base<2>(offset, size), _freq1(freq1), _freq2(freq2), _fade1(fadeinrate), _fade2(fadeoutrate) { }
start(Player_MOD * mod,int id,const byte * data)452 virtual void start(Player_MOD *mod, int id, const byte *data) {
453 _mod = mod;
454 _id = id;
455 char *tmp_data1 = (char *)malloc(_size);
456 char *tmp_data2 = (char *)malloc(_size);
457 memcpy(tmp_data1, data + _offset, _size);
458 memcpy(tmp_data2, data + _offset, _size);
459 _curvol = 1;
460 _dir = 0;
461 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, 1, 0, _size, -127);
462 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, 1, 0, _size, 127);
463 }
update()464 virtual bool update() {
465 assert(_id);
466 if (_dir == 0) {
467 _curvol += _fade1;
468 if (_curvol > 0x3F) {
469 _curvol = 0x3F;
470 _dir = 1;
471 }
472 } else {
473 _curvol -= _fade2;
474 if (_curvol < 1)
475 return false;
476 }
477 _mod->setChannelVol(_id | 0x000, (_curvol << 1) | (_curvol >> 5));
478 _mod->setChannelVol(_id | 0x100, (_curvol << 1) | (_curvol >> 5));
479 return true;
480 }
481 private:
482 const uint16 _freq1;
483 const uint16 _freq2;
484 const uint16 _fade1;
485 const uint16 _fade2;
486
487 int _curvol;
488 int _dir;
489 };
490
491 // plays a single looped waveform, starting at one frequency and at full volume, bending down to another frequency, and then fading volume to zero
492 // used in Maniac Mansion for the tentacle sounds
493 class V2A_Sound_Special_ManiacTentacle : public V2A_Sound_Base<1> {
494 public:
V2A_Sound_Special_ManiacTentacle(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint16 step)495 V2A_Sound_Special_ManiacTentacle(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step) :
496 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _step(step) { }
start(Player_MOD * mod,int id,const byte * data)497 virtual void start(Player_MOD *mod, int id, const byte *data) {
498 _mod = mod;
499 _id = id;
500 char *tmp_data = (char *)malloc(_size);
501 memcpy(tmp_data, data + _offset, _size);
502 _curfreq = _freq1;
503 _curvol = 0x3F;
504 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
505 }
update()506 virtual bool update() {
507 assert(_id);
508 if (_curfreq > _freq2)
509 _curvol = 0x3F + _freq2 - _curfreq;
510 if (_curvol < 1)
511 return false;
512 _curfreq += _step;
513 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
514 _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
515 return true;
516 }
517 private:
518 const uint16 _freq1;
519 const uint16 _freq2;
520 const uint16 _step;
521
522 uint16 _curfreq;
523 int _curvol;
524 };
525
526 // plays a single looped waveform, starting at one frequency, bending down to another frequency, and then back up to the original frequency
527 // used for electronic noises
528 class V2A_Sound_Special_Maniac59 : public V2A_Sound_Base<1> {
529 public:
V2A_Sound_Special_Maniac59(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint16 step,uint8 vol)530 V2A_Sound_Special_Maniac59(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step, uint8 vol) :
531 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _step(step), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)532 virtual void start(Player_MOD *mod, int id, const byte *data) {
533 _mod = mod;
534 _id = id;
535 char *tmp_data = (char *)malloc(_size);
536 memcpy(tmp_data, data + _offset, _size);
537 int vol = (_vol << 2) | (_vol >> 4);
538 _curfreq = _freq1;
539 _dir = 2;
540 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, vol, 0, _size);
541 }
update()542 virtual bool update() {
543 assert(_id);
544 if (_dir == 2) {
545 _curfreq += _step;
546 if (_curfreq > _freq2) {
547 _curfreq = _freq2;
548 _dir = 1;
549 }
550 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
551 } else if (_dir == 1) {
552 _curfreq -= _step;
553 if (_curfreq < _freq1) {
554 _curfreq = _freq1;
555 _dir = 0;
556 }
557 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
558 }
559 return true;
560 }
561 private:
562 const uint16 _freq1;
563 const uint16 _freq2;
564 const uint16 _step;
565 const uint8 _vol;
566
567 uint16 _curfreq;
568 int _dir;
569 };
570
571 // plays a single looped waveform, simultaneously bending the frequency downward and slowly fading volume to zero
572 // don't remember where this one is used
573 class V2A_Sound_Special_Maniac61 : public V2A_Sound_Base<1> {
574 public:
V2A_Sound_Special_Maniac61(uint16 offset,uint16 size,uint16 freq1,uint16 freq2)575 V2A_Sound_Special_Maniac61(uint16 offset, uint16 size, uint16 freq1, uint16 freq2) :
576 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2) { }
start(Player_MOD * mod,int id,const byte * data)577 virtual void start(Player_MOD *mod, int id, const byte *data) {
578 _mod = mod;
579 _id = id;
580 char *tmp_data = (char *)malloc(_size);
581 memcpy(tmp_data, data + _offset, _size);
582 _curfreq = _freq1;
583 _curvol = 0x3F;
584 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
585 }
update()586 virtual bool update() {
587 assert(_id);
588 _curfreq++;
589 if (!(_curfreq & 3))
590 _curvol--;
591 if ((_curfreq == _freq2) || (_curvol == 0))
592 return false;
593 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
594 _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
595 return true;
596 }
597 private:
598 const uint16 _freq1;
599 const uint16 _freq2;
600
601 uint16 _curfreq;
602 uint8 _curvol;
603 };
604
605 // intermittently plays two looped waveforms for a specific duration
606 // used for ringing telephones
607 class V2A_Sound_Special_ManiacPhone : public V2A_Sound_Base<2> {
608 public:
V2A_Sound_Special_ManiacPhone(uint16 offset,uint16 size,uint16 freq1,uint8 vol1,uint16 freq2,uint8 vol2,uint16 numframes,uint8 playwidth,uint8 loopwidth)609 V2A_Sound_Special_ManiacPhone(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2, uint16 numframes, uint8 playwidth, uint8 loopwidth) :
610 V2A_Sound_Base<2>(offset, size), _freq1(freq1), _vol1(vol1), _freq2(freq2), _vol2(vol2), _duration(numframes), _playwidth(playwidth), _loopwidth(loopwidth) { }
start(Player_MOD * mod,int id,const byte * data)611 virtual void start(Player_MOD *mod, int id, const byte *data) {
612 _mod = mod;
613 _id = id;
614 _data = (char *)malloc(READ_LE_UINT16(data));
615 memcpy(_data, data, READ_LE_UINT16(data));
616 soundon();
617 _ticks = 0;
618 _loop = 0;
619 }
update()620 virtual bool update() {
621 assert(_id);
622 if (_loop == _playwidth) {
623 _mod->stopChannel(_id | 0x000);
624 _mod->stopChannel(_id | 0x100);
625 }
626 if (_loop == _loopwidth) {
627 _loop = 0;
628 soundon();
629 }
630 _loop++;
631 _ticks++;
632 if (_ticks >= _duration)
633 return false;
634 return true;
635 }
636 private:
637 const uint16 _freq1;
638 const uint8 _vol1;
639 const uint16 _freq2;
640 const uint8 _vol2;
641 const uint16 _duration;
642 const uint8 _playwidth;
643 const uint8 _loopwidth;
644
645 int _ticks;
646 int _loop;
647
soundon()648 void soundon() {
649 char *tmp_data1 = (char *)malloc(_size);
650 char *tmp_data2 = (char *)malloc(_size);
651 memcpy(tmp_data1, _data + _offset, _size);
652 memcpy(tmp_data2, _data + _offset, _size);
653 int vol1 = (_vol1 << 1) | (_vol1 >> 5);
654 int vol2 = (_vol2 << 1) | (_vol2 >> 5);
655 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, vol1, 0, _size, -127);
656 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, vol2, 0, _size, 127);
657 }
658 };
659
660 // intermittently plays a single waveform for a specified duration
661 // used when applying a wrench to a pipe
662 class V2A_Sound_Special_Maniac46 : public V2A_Sound_Base<1> {
663 public:
V2A_Sound_Special_Maniac46(uint16 offset,uint16 size,uint16 freq,uint8 vol,uint8 loopwidth,uint8 numloops)664 V2A_Sound_Special_Maniac46(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 loopwidth, uint8 numloops) :
665 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol), _loopwidth(loopwidth), _numloops(numloops) { }
start(Player_MOD * mod,int id,const byte * data)666 virtual void start(Player_MOD *mod, int id, const byte *data) {
667 _mod = mod;
668 _id = id;
669 _data = (char *)malloc(READ_LE_UINT16(data));
670 memcpy(_data, data, READ_LE_UINT16(data));
671 soundon();
672 _loop = 0;
673 _loopctr = 0;
674 }
update()675 virtual bool update() {
676 assert(_id);
677 _loop++;
678 if (_loop == _loopwidth) {
679 _loop = 0;
680 _loopctr++;
681 if (_loopctr == _numloops)
682 return false;
683 _mod->stopChannel(_id);
684 soundon();
685 }
686 return true;
687 }
688 private:
689 const uint16 _freq;
690 const uint8 _vol;
691 const uint8 _loopwidth;
692 const uint8 _numloops;
693
694 int _loop;
695 int _loopctr;
696
soundon()697 void soundon() {
698 char *tmp_data = (char *)malloc(_size);
699 memcpy(tmp_data, _data + _offset, _size);
700 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, (_vol << 2) | (_vol >> 4), 0, 0);
701 }
702 };
703
704 // plays a single waveform at irregular intervals for a specified number of frames, possibly looped
705 // used for typewriter noises, as well as tapping on the bus in Zak McKracken
706 class V2A_Sound_Special_ManiacTypewriter : public V2A_Sound_Base<1> {
707 public:
V2A_Sound_Special_ManiacTypewriter(uint16 offset,uint16 size,uint16 freq,uint8 vol,uint8 numdurs,const uint8 * durations,bool looped)708 V2A_Sound_Special_ManiacTypewriter(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 numdurs, const uint8 *durations, bool looped) :
709 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol), _numdurs(numdurs), _durations(durations), _looped(looped) { }
start(Player_MOD * mod,int id,const byte * data)710 virtual void start(Player_MOD *mod, int id, const byte *data) {
711 _mod = mod;
712 _id = id;
713 _data = (char *)malloc(READ_LE_UINT16(data));
714 memcpy(_data, data, READ_LE_UINT16(data));
715 soundon();
716 _curdur = 0;
717 _ticks = _durations[_curdur++];
718 }
update()719 virtual bool update() {
720 assert(_id);
721 _ticks--;
722 if (!_ticks) {
723 if (_curdur == _numdurs) {
724 if (_looped)
725 _curdur = 0;
726 else
727 return false;
728 }
729 _mod->stopChannel(_id);
730 soundon();
731 _ticks = _durations[_curdur++];
732 }
733 return true;
734 }
735 private:
736 const uint16 _freq;
737 const uint8 _vol;
738 const uint8 _numdurs;
739 const uint8 *_durations;
740 const bool _looped;
741
742 int _ticks;
743 int _curdur;
744
soundon()745 void soundon() {
746 char *tmp_data = (char *)malloc(_size);
747 memcpy(tmp_data, _data + _offset, _size);
748 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, (_vol << 2) | (_vol >> 4), 0, 0);
749 }
750 };
751
752 // plays two looped waveforms pitch bending up at various predefined rates
753 // used for some sort of siren-like noise in Maniac Mansion
754 class V2A_Sound_Special_Maniac44 : public V2A_Sound_Base<2> {
755 public:
V2A_Sound_Special_Maniac44(uint16 offset1,uint16 size1,uint16 offset2,uint16 size2,uint16 freq1,uint16 freq2,uint8 vol)756 V2A_Sound_Special_Maniac44(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2, uint8 vol) :
757 _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq1(freq1), _freq2(freq2), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)758 virtual void start(Player_MOD *mod, int id, const byte *data) {
759 _mod = mod;
760 _id = id;
761 _data = (char *)malloc(READ_LE_UINT16(data));
762 memcpy(_data, data, READ_LE_UINT16(data));
763
764 _loopnum = 1;
765 _step = 2;
766 _curfreq = _freq1;
767
768 soundon(_data + _offset1, _size1);
769 }
update()770 virtual bool update() {
771 assert(_id);
772 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _curfreq);
773 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_curfreq + 3));
774 _curfreq -= _step;
775 if (_loopnum == 7) {
776 if ((BASE_FREQUENCY / _curfreq) >= 65536)
777 return false;
778 else
779 return true;
780 }
781 if (_curfreq >= _freq2)
782 return true;
783 const char steps[8] = {0, 2, 2, 3, 4, 8, 15, 2};
784 _curfreq = _freq1;
785 _step = steps[++_loopnum];
786 if (_loopnum == 7) {
787 _mod->stopChannel(_id | 0x000);
788 _mod->stopChannel(_id | 0x100);
789 soundon(_data + _offset2, _size2);
790 }
791 return true;
792 }
793 private:
794 const uint16 _offset1;
795 const uint16 _size1;
796 const uint16 _offset2;
797 const uint16 _size2;
798 const uint16 _freq1;
799 const uint16 _freq2;
800 const uint8 _vol;
801
802 int _curfreq;
803 uint16 _loopnum;
804 uint16 _step;
805
soundon(const char * data,int size)806 void soundon(const char *data, int size) {
807 char *tmp_data1 = (char *)malloc(size);
808 char *tmp_data2 = (char *)malloc(size);
809 memcpy(tmp_data1, data, size);
810 memcpy(tmp_data2, data, size);
811 int vol = (_vol << 1) | (_vol >> 5);
812 _mod->startChannel(_id | 0x000, tmp_data1, size, BASE_FREQUENCY / _curfreq, vol, 0, size, -127);
813 _mod->startChannel(_id | 0x100, tmp_data2, size, BASE_FREQUENCY / (_curfreq + 3), vol, 0, size, 127);
814 }
815 };
816
817 // plays 4 looped waveforms, each at modulating frequencies
818 // used for the siren noise in Maniac Mansion
819 class V2A_Sound_Special_Maniac32 : public V2A_Sound_Base<4> {
820 public:
V2A_Sound_Special_Maniac32(uint16 offset1,uint16 size1,uint16 offset2,uint16 size2,uint8 vol)821 V2A_Sound_Special_Maniac32(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint8 vol) :
822 _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)823 virtual void start(Player_MOD *mod, int id, const byte *data) {
824 _mod = mod;
825 _id = id;
826
827 _freq1 = 0x02D0;
828 _step1 = -0x000A;
829 _freq2 = 0x0122;
830 _step2 = 0x000A;
831 _freq3 = 0x02BC;
832 _step3 = -0x0005;
833 _freq4 = 0x010E;
834 _step4 = 0x0007;
835
836 char *tmp_data1 = (char *)malloc(_size1);
837 char *tmp_data2 = (char *)malloc(_size2);
838 char *tmp_data3 = (char *)malloc(_size1);
839 char *tmp_data4 = (char *)malloc(_size2);
840 memcpy(tmp_data1, data + _offset1, _size1);
841 memcpy(tmp_data2, data + _offset2, _size2);
842 memcpy(tmp_data3, data + _offset1, _size1);
843 memcpy(tmp_data4, data + _offset2, _size2);
844 _mod->startChannel(_id | 0x000, tmp_data1, _size1, BASE_FREQUENCY / _freq1, _vol, 0, _size1, -127);
845 _mod->startChannel(_id | 0x100, tmp_data2, _size2, BASE_FREQUENCY / _freq2, _vol, 0, _size2, 127);
846 _mod->startChannel(_id | 0x200, tmp_data3, _size1, BASE_FREQUENCY / _freq3, _vol, 0, _size1, 127);
847 _mod->startChannel(_id | 0x300, tmp_data4, _size2, BASE_FREQUENCY / _freq4, _vol, 0, _size2, -127);
848 }
update()849 virtual bool update() {
850 assert(_id);
851 updatefreq(_freq1, _step1, 0x00AA, 0x00FA);
852 updatefreq(_freq2, _step2, 0x019A, 0x03B6);
853 updatefreq(_freq3, _step3, 0x00AA, 0x00FA);
854 updatefreq(_freq4, _step4, 0x019A, 0x03B6);
855 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq1);
856 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / _freq2);
857 _mod->setChannelFreq(_id | 0x200, BASE_FREQUENCY / _freq3);
858 _mod->setChannelFreq(_id | 0x300, BASE_FREQUENCY / _freq4);
859 return true;
860 }
861 private:
862 const uint16 _offset1;
863 const uint16 _size1;
864 const uint16 _offset2;
865 const uint16 _size2;
866 const uint8 _vol;
867
868 uint16 _freq1;
869 int16 _step1;
870 uint16 _freq2;
871 int16 _step2;
872 uint16 _freq3;
873 int16 _step3;
874 uint16 _freq4;
875 int16 _step4;
876
updatefreq(uint16 & freq,int16 & step,uint16 min,uint16 max)877 void updatefreq(uint16 &freq, int16 &step, uint16 min, uint16 max) {
878 freq += step;
879 if (freq <= min) {
880 freq = min;
881 step = -step;
882 }
883 if (freq >= max) {
884 freq = max;
885 step = -step;
886 }
887 }
888 };
889
890 // plays 4 looped waveforms
891 // used in the white crystal chamber
892 class V2A_Sound_Special_Zak70 : public V2A_Sound_Base<4> {
893 public:
V2A_Sound_Special_Zak70(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint16 freq3,uint16 freq4,uint8 vol)894 V2A_Sound_Special_Zak70(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol) :
895 V2A_Sound_Base<4>(offset, size), _freq1(freq1), _freq2(freq2), _freq3(freq3), _freq4(freq4), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)896 virtual void start(Player_MOD *mod, int id, const byte *data) {
897 _mod = mod;
898 _id = id;
899
900 char *tmp_data1 = (char *)malloc(_size);
901 char *tmp_data2 = (char *)malloc(_size);
902 char *tmp_data3 = (char *)malloc(_size);
903 char *tmp_data4 = (char *)malloc(_size);
904 memcpy(tmp_data1, data + _offset, _size);
905 memcpy(tmp_data2, data + _offset, _size);
906 memcpy(tmp_data3, data + _offset, _size);
907 memcpy(tmp_data4, data + _offset, _size);
908 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, _vol, 0, _size, -127);
909 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, _vol, 0, _size, 127);
910 _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq3, _vol, 0, _size, 127);
911 _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq4, _vol, 0, _size, -127);
912 }
update()913 virtual bool update() {
914 assert(_id);
915 return true;
916 }
917 protected:
918 const uint16 _freq1;
919 const uint16 _freq2;
920 const uint16 _freq3;
921 const uint16 _freq4;
922 const uint8 _vol;
923 };
924
925 // plays 4 looped waveforms and fades volume to zero after a specific delay
926 // used when the Mindbender disappears
927 class V2A_Sound_Special_Zak101 : public V2A_Sound_Special_Zak70 {
928 public:
V2A_Sound_Special_Zak101(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint16 freq3,uint16 freq4,uint8 vol,uint16 dur)929 V2A_Sound_Special_Zak101(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol, uint16 dur) :
930 V2A_Sound_Special_Zak70(offset, size, freq1, freq2, freq3, freq4, vol), _dur(dur) { }
start(Player_MOD * mod,int id,const byte * data)931 virtual void start(Player_MOD *mod, int id, const byte *data) {
932 V2A_Sound_Special_Zak70::start(mod, id, data);
933 _ticks = _dur;
934 }
update()935 virtual bool update() {
936 assert(_id);
937 if (!--_ticks)
938 return false;
939 if (_ticks < _vol) {
940 _mod->setChannelVol(_id | 0x000, _ticks);
941 _mod->setChannelVol(_id | 0x100, _ticks);
942 _mod->setChannelVol(_id | 0x200, _ticks);
943 _mod->setChannelVol(_id | 0x300, _ticks);
944 }
945 return true;
946 }
947 private:
948 const uint16 _dur;
949
950 int _ticks;
951 };
952
953 // plays a single looped waveform and slowly fades volume to zero
954 // used when refilling oxygen
955 class V2A_Sound_Special_Zak37 : public V2A_Sound_Base<1> {
956 public:
V2A_Sound_Special_Zak37(uint16 offset,uint16 size,uint16 freq,uint8 vol)957 V2A_Sound_Special_Zak37(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
958 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)959 virtual void start(Player_MOD *mod, int id, const byte *data) {
960 _mod = mod;
961 _id = id;
962 char *tmp_data = (char *)malloc(_size);
963 memcpy(tmp_data, data + _offset, _size);
964 _curvol = _vol << 2;
965 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, _curvol, 0, _size);
966 }
update()967 virtual bool update() {
968 assert(_id);
969 if (!--_curvol)
970 return false;
971 _mod->setChannelVol(_id, _curvol);
972 return true;
973 }
974 private:
975 const uint16 _freq;
976 const uint8 _vol;
977
978 int _curvol;
979 };
980
981 // plays a single looped waveform, slowly bending from one frequency to another and then slowly fading volume from max to zero
982 // used in Zak for airplane taking off and landing
983 class V2A_Sound_Special_ZakAirplane : public V2A_Sound_Base<1> {
984 public:
V2A_Sound_Special_ZakAirplane(uint16 offset,uint16 size,uint16 freq1,uint16 freq2)985 V2A_Sound_Special_ZakAirplane(uint16 offset, uint16 size, uint16 freq1, uint16 freq2) :
986 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2) { }
start(Player_MOD * mod,int id,const byte * data)987 virtual void start(Player_MOD *mod, int id, const byte *data) {
988 _mod = mod;
989 _id = id;
990 char *tmp_data = (char *)malloc(_size);
991 memcpy(tmp_data, data + _offset, _size);
992 _curfreq = _freq1;
993 _curvol = 0x3F;
994 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
995 _ticks = 0;
996 }
update()997 virtual bool update() {
998 assert(_id);
999 _ticks++;
1000 if (_ticks < 4)
1001 return true;
1002 _ticks = 0;
1003 if (_curfreq == _freq2) {
1004 _curvol--;
1005 if (_curvol == 0)
1006 return false;
1007 _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
1008 } else {
1009 if (_freq1 < _freq2)
1010 _curfreq++;
1011 else
1012 _curfreq--;
1013 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
1014 }
1015 return true;
1016 }
1017 private:
1018 const uint16 _freq1;
1019 const uint16 _freq2;
1020
1021 uint16 _curfreq;
1022 int _curvol;
1023 int _ticks;
1024 };
1025
1026 // plays 4 looped waveforms, starting at specific frequencies and bending at different rates while fading volume to zero
1027 // used when the white crystal machine turns off
1028 class V2A_Sound_Special_Zak71 : public V2A_Sound_Base<4> {
1029 public:
V2A_Sound_Special_Zak71(uint16 offset,uint16 size)1030 V2A_Sound_Special_Zak71(uint16 offset, uint16 size) :
1031 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1032 virtual void start(Player_MOD *mod, int id, const byte *data) {
1033 _mod = mod;
1034 _id = id;
1035
1036 _freq1 = 0x00C8;
1037 _freq2 = 0x0190;
1038 _freq3 = 0x0320;
1039 _freq4 = 0x0640;
1040 _vol = 0x78;
1041
1042 char *tmp_data1 = (char *)malloc(_size);
1043 char *tmp_data2 = (char *)malloc(_size);
1044 char *tmp_data3 = (char *)malloc(_size);
1045 char *tmp_data4 = (char *)malloc(_size);
1046 memcpy(tmp_data1, data + _offset, _size);
1047 memcpy(tmp_data2, data + _offset, _size);
1048 memcpy(tmp_data3, data + _offset, _size);
1049 memcpy(tmp_data4, data + _offset, _size);
1050 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, MIN((_vol >> 1) + 3, 0x32), 0, _size, -127);
1051 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, MIN((_vol >> 1) + 3, 0x32), 0, _size, 127);
1052 _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq3, MIN((_vol >> 1) + 3, 0x32), 0, _size, 127);
1053 _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq4, MIN((_vol >> 1) + 3, 0x32), 0, _size, -127);
1054 }
update()1055 virtual bool update() {
1056 assert(_id);
1057 _freq1 += 0x14;
1058 _freq2 += 0x1E;
1059 _freq3 += 0x32;
1060 _freq4 += 0x50;
1061 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq1);
1062 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / _freq2);
1063 _mod->setChannelFreq(_id | 0x200, BASE_FREQUENCY / _freq3);
1064 _mod->setChannelFreq(_id | 0x300, BASE_FREQUENCY / _freq4);
1065 _vol--;
1066 if (_vol == 0)
1067 return false;
1068 _mod->setChannelVol(_id | 0x000, MIN((_vol >> 1) + 3, 0x32));
1069 _mod->setChannelVol(_id | 0x100, MIN((_vol >> 1) + 3, 0x32));
1070 _mod->setChannelVol(_id | 0x200, MIN((_vol >> 1) + 3, 0x32));
1071 _mod->setChannelVol(_id | 0x300, MIN((_vol >> 1) + 3, 0x32));
1072 return true;
1073 }
1074 private:
1075 const uint16 _offset;
1076 const uint16 _size;
1077
1078 uint16 _freq1;
1079 uint16 _freq2;
1080 uint16 _freq3;
1081 uint16 _freq4;
1082 uint8 _vol;
1083 };
1084
1085 // plays a single looped waveform, bending the frequency upward at a varying rate
1086 // used when the Skolarian device activates
1087 class V2A_Sound_Special_Zak99 : public V2A_Sound_Base<1> {
1088 public:
V2A_Sound_Special_Zak99(uint16 offset,uint16 size,uint16 freq1,uint16 freq2,uint8 vol)1089 V2A_Sound_Special_Zak99(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol) :
1090 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _vol(vol) { }
start(Player_MOD * mod,int id,const byte * data)1091 virtual void start(Player_MOD *mod, int id, const byte *data) {
1092 _mod = mod;
1093 _id = id;
1094 char *tmp_data = (char *)malloc(_size);
1095 memcpy(tmp_data, data + _offset, _size);
1096 _curfreq = _freq1;
1097 _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_vol << 2) | (_vol >> 4), 0, _size);
1098 _bendrate = 8;
1099 _bendctr = 100;
1100 _holdctr = 30;
1101 }
update()1102 virtual bool update() {
1103 assert(_id);
1104 if (_curfreq >= _freq2) {
1105 _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
1106 _curfreq -= _bendrate;
1107 if (--_bendctr)
1108 return true;
1109 _bendrate--;
1110 if (_bendrate < 2)
1111 _bendrate = 2;
1112 } else {
1113 if (!--_holdctr)
1114 return false;
1115 }
1116 return true;
1117 }
1118 private:
1119 const uint16 _freq1;
1120 const uint16 _freq2;
1121 const uint16 _vol;
1122
1123 uint16 _curfreq;
1124 uint16 _bendrate;
1125 uint16 _bendctr;
1126 uint16 _holdctr;
1127 };
1128
1129 // plays one waveform, then switches to a different looped waveform and slowly fades volume to zero
1130 // used when depressurizing the hostel
1131 class V2A_Sound_Special_Zak54 : public V2A_Sound_Base<1> {
1132 public:
V2A_Sound_Special_Zak54(uint16 offset1,uint16 size1,uint16 offset2,uint16 size2,uint16 freq)1133 V2A_Sound_Special_Zak54(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq) :
1134 _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq(freq) { }
start(Player_MOD * mod,int id,const byte * data)1135 virtual void start(Player_MOD *mod, int id, const byte *data) {
1136 _mod = mod;
1137 _id = id;
1138 _data = (char *)malloc(READ_LE_UINT16(data));
1139 memcpy(_data, data, READ_LE_UINT16(data));
1140 char *tmp_data = (char *)malloc(_size1);
1141 memcpy(tmp_data, data + _offset1, _size1);
1142 _vol = 0xFC;
1143 _mod->startChannel(_id, tmp_data, _size1, BASE_FREQUENCY / _freq, _vol, 0, _size1);
1144 _loop = _size1 * _freq * 60 / BASE_FREQUENCY;
1145 }
update()1146 virtual bool update() {
1147 assert(_id);
1148 if (!_loop) {
1149 _vol--;
1150 if (_vol)
1151 _mod->setChannelVol(_id, _vol);
1152 else
1153 return false;
1154 } else if (!--_loop) {
1155 _mod->stopChannel(_id);
1156 char *tmp_data = (char *)malloc(_size2);
1157 memcpy(tmp_data, _data + _offset2, _size2);
1158 _mod->startChannel(_id, tmp_data, _size2, BASE_FREQUENCY / _freq, _vol, 0, _size2);
1159 }
1160 return true;
1161 }
1162
1163 private:
1164 const uint16 _offset1;
1165 const uint16 _offset2;
1166 const uint16 _size1;
1167 const uint16 _size2;
1168 const uint16 _freq;
1169
1170 int _vol;
1171 int _loop;
1172 };
1173
1174 // plays 2 looped waveforms at different frequencies, pulsing at different frequencies and ramping the volume up and down once
1175 // used when abducted at the Bermuda Triangle
1176 class V2A_Sound_Special_Zak110 : public V2A_Sound_Base<2> {
1177 public:
V2A_Sound_Special_Zak110(uint16 offset1,uint16 size1,uint16 offset2,uint16 size2,uint16 freq1,uint16 freq2)1178 V2A_Sound_Special_Zak110(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2) :
1179 _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq1(freq1), _freq2(freq2) { }
start(Player_MOD * mod,int id,const byte * data)1180 virtual void start(Player_MOD *mod, int id, const byte *data) {
1181 _mod = mod;
1182 _id = id;
1183 _data = (char *)malloc(READ_LE_UINT16(data));
1184 memcpy(_data, data, READ_LE_UINT16(data));
1185
1186 _loopnum = 0;
1187 _vol = 0x1500;
1188 _beepcount = 0;
1189 }
update()1190 virtual bool update() {
1191 char *tmp_data;
1192 assert(_id);
1193
1194 int vol = (((_vol >> 7) & 0x7E) | ((_vol >> 15) & 0x01));
1195 _beepcount++;
1196
1197 switch (_beepcount & 0x3) {
1198 case 0:
1199 _mod->stopChannel(_id | 0x000);
1200 break;
1201 case 1:
1202 tmp_data = (char *)malloc(_size1);
1203 memcpy(tmp_data, _data + _offset1, _size1);
1204 _mod->startChannel(_id | 0x000, tmp_data, _size1, BASE_FREQUENCY / _freq1, vol, 0, _size1, -127);
1205 break;
1206 default:
1207 _mod->setChannelVol(_id | 0x000, vol);
1208 break;
1209 }
1210
1211 switch (_beepcount & 0x7) {
1212 case 0:
1213 _mod->stopChannel(_id | 0x100);
1214 break;
1215 case 1:
1216 tmp_data = (char *)malloc(_size2);
1217 memcpy(tmp_data, _data + _offset2, _size2);
1218 _mod->startChannel(_id | 0x100, tmp_data, _size2, BASE_FREQUENCY / _freq2, vol, 0, _size2, 127);
1219 break;
1220 default:
1221 _mod->setChannelVol(_id | 0x100, vol);
1222 break;
1223 }
1224
1225 if (_loopnum == 0) {
1226 _vol += 0x80;
1227 if (_vol == 0x4000) {
1228 _vol = 0x3F00;
1229 _loopnum = 1;
1230 }
1231 } else if (_loopnum == 1) {
1232 _vol -= 0x20;
1233 if (_vol == 0x2000)
1234 _loopnum = 2;
1235 }
1236 return true;
1237 }
1238 private:
1239 const uint16 _offset1;
1240 const uint16 _size1;
1241 const uint16 _offset2;
1242 const uint16 _size2;
1243 const uint16 _freq1;
1244 const uint16 _freq2;
1245
1246 uint16 _loopnum;
1247 uint16 _vol;
1248 uint16 _beepcount;
1249 };
1250
1251 // plays a stereo siren, sweeping up and down quickly several times before sweeping up slowly, stopping, and then going silent
1252 // door orb sound in the Mars Face
1253 class V2A_Sound_Special_Zak32 : public V2A_Sound_Base<2> {
1254 public:
V2A_Sound_Special_Zak32(uint16 offset1,uint16 offset2,uint16 size1,uint16 size2)1255 V2A_Sound_Special_Zak32(uint16 offset1, uint16 offset2, uint16 size1, uint16 size2) :
1256 _offset1(offset1), _offset2(offset2), _size1(size1), _size2(size2) { }
start(Player_MOD * mod,int id,const byte * data)1257 virtual void start(Player_MOD *mod, int id, const byte *data) {
1258 _mod = mod;
1259 _id = id;
1260 _data = (char *)malloc(READ_LE_UINT16(data));
1261 memcpy(_data, data, READ_LE_UINT16(data));
1262
1263 _loopnum = 1;
1264 _freqmod = -4;
1265 _freq = 0x00C8;
1266
1267 char *tmp_data1 = (char *)malloc(_size1);
1268 char *tmp_data2 = (char *)malloc(_size1);
1269 memcpy(tmp_data1, _data + _offset1, _size1);
1270 memcpy(tmp_data2, _data + _offset1, _size1);
1271 _mod->startChannel(_id | 0x000, tmp_data1, _size1, BASE_FREQUENCY / _freq, 0x7F, 0, _size1, -127);
1272 _mod->startChannel(_id | 0x100, tmp_data2, _size1, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size1, 127);
1273 }
update()1274 virtual bool update() {
1275 assert(_id);
1276
1277 if (_loopnum < 7) {
1278 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
1279 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
1280 _freq += _freqmod;
1281 if (_freq <= 0x80)
1282 _freqmod = -_freqmod;
1283 else if (_freq >= 0xC8) {
1284 _freqmod = -_freqmod;
1285 _loopnum++;
1286 if (_loopnum == 7) {
1287 _freq = 0x00C8;
1288 _freqmod = 2;
1289 }
1290 }
1291 return true;
1292 } else {
1293 if (_loopnum == 7) {
1294 _mod->stopChannel(_id | 0x000);
1295 _mod->stopChannel(_id | 0x100);
1296
1297 char *tmp_data1 = (char *)malloc(_size2);
1298 char *tmp_data2 = (char *)malloc(_size2);
1299 memcpy(tmp_data1, _data + _offset2, _size2);
1300 memcpy(tmp_data2, _data + _offset2, _size2);
1301 _mod->startChannel(_id | 0x000, tmp_data1, _size2, BASE_FREQUENCY / (_freq), 0x7F, 0, _size2, -127);
1302 _mod->startChannel(_id | 0x100, tmp_data2, _size2, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size2, 127);
1303 _loopnum++;
1304 } else {
1305 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
1306 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
1307 }
1308 _freq -= _freqmod;
1309 if (_freq > 0)
1310 return true;
1311 else
1312 return false;
1313 }
1314 }
1315 private:
1316 const uint16 _offset1;
1317 const uint16 _offset2;
1318 const uint16 _size1;
1319 const uint16 _size2;
1320
1321 uint16 _loopnum;
1322 int16 _freqmod;
1323 uint16 _freq;
1324 };
1325
1326 // plays a looped waveform, increasing frequency and reducing volume once the frequency reaches a certain point
1327 // probably used for some sort of vehicle sound
1328 class V2A_Sound_Special_Zak52 : public V2A_Sound_Base<1> {
1329 public:
V2A_Sound_Special_Zak52(uint16 offset,uint16 size)1330 V2A_Sound_Special_Zak52(uint16 offset, uint16 size) :
1331 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1332 virtual void start(Player_MOD *mod, int id, const byte *data) {
1333 _mod = mod;
1334 _id = id;
1335 _data = (char *)malloc(READ_LE_UINT16(data));
1336 memcpy(_data, data, READ_LE_UINT16(data));
1337
1338 _curfreq = 0x0312;
1339
1340 char *tmp_data = (char *)malloc(_size);
1341 memcpy(tmp_data, _data + _offset, _size);
1342 _mod->startChannel(_id | 0x000, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0xFF, 0, _size, -127);
1343 }
update()1344 virtual bool update() {
1345 assert(_id);
1346 int vol = (_curfreq - 0xC8) >> 3;
1347 if (vol > 0x3F)
1348 vol = 0x3F;
1349 vol = (vol << 2) | (vol >> 4);
1350 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _curfreq);
1351 _mod->setChannelVol(_id | 0x000, vol);
1352 _curfreq--;
1353 if (_curfreq >= 0x107)
1354 return true;
1355 else
1356 return false;
1357 }
1358 private:
1359 const uint16 _offset;
1360 const uint16 _size;
1361
1362 uint16 _curfreq;
1363 };
1364
1365 // plays a looped waveform, sweeping the frequency up while modulating it (alternating which channel updates) and fading volume out
1366 // used when teleporting out with the yellow crystal
1367 class V2A_Sound_Special_Zak61 : public V2A_Sound_Base<2> {
1368 public:
V2A_Sound_Special_Zak61(uint16 offset,uint16 size)1369 V2A_Sound_Special_Zak61(uint16 offset, uint16 size) :
1370 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1371 virtual void start(Player_MOD *mod, int id, const byte *data) {
1372 _mod = mod;
1373 _id = id;
1374 _data = (char *)malloc(READ_LE_UINT16(data));
1375 memcpy(_data, data, READ_LE_UINT16(data));
1376
1377 _loop = 1;
1378 _curfreq = 0x01F4;
1379
1380 char *tmp_data1 = (char *)malloc(_size);
1381 char *tmp_data2 = (char *)malloc(_size);
1382 memcpy(tmp_data1, _data + _offset, _size);
1383 memcpy(tmp_data2, _data + _offset, _size);
1384 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
1385 // start 2nd channel silent
1386 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
1387 }
update()1388 virtual bool update() {
1389 assert(_id);
1390 int freq = (_loop << 4) + _curfreq;
1391 int vol = freq - 0x76;
1392 if (vol > 0x3F)
1393 vol = 0x3F;
1394 vol = (vol << 1) | (vol >> 5);
1395 switch (_loop) {
1396 case 0:
1397 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
1398 _mod->setChannelVol(_id | 0x000, vol);
1399 break;
1400 case 1:
1401 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
1402 _mod->setChannelVol(_id | 0x100, vol);
1403 break;
1404 }
1405 _loop = (_loop + 1) & 3;
1406 if (!_loop) {
1407 _curfreq -= 4;
1408 if (_curfreq <= 0x80)
1409 return false;
1410 }
1411 return true;
1412 }
1413 private:
1414 const uint16 _offset;
1415 const uint16 _size;
1416
1417 uint16 _loop;
1418 uint16 _curfreq;
1419 };
1420
1421 // just like Zak61, but sweeps frequency in the other direction
1422 // used when teleporting in with the yellow crystal
1423 class V2A_Sound_Special_Zak62 : public V2A_Sound_Base<2> {
1424 public:
V2A_Sound_Special_Zak62(uint16 offset,uint16 size)1425 V2A_Sound_Special_Zak62(uint16 offset, uint16 size) :
1426 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1427 virtual void start(Player_MOD *mod, int id, const byte *data) {
1428 _mod = mod;
1429 _id = id;
1430 _data = (char *)malloc(READ_LE_UINT16(data));
1431 memcpy(_data, data, READ_LE_UINT16(data));
1432
1433 _loop = 1;
1434 _curfreq = 0x0080;
1435
1436 char *tmp_data1 = (char *)malloc(_size);
1437 char *tmp_data2 = (char *)malloc(_size);
1438 memcpy(tmp_data1, _data + _offset, _size);
1439 memcpy(tmp_data2, _data + _offset, _size);
1440 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
1441 // start 2nd channel silent
1442 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
1443 }
update()1444 virtual bool update() {
1445 assert(_id);
1446 int freq = (_loop << 4) + _curfreq;
1447 int vol = 0x0200 - freq;
1448 if (vol > 0x3F)
1449 vol = 0x3F;
1450 vol = (vol << 1) | (vol >> 5);
1451 switch (_loop) {
1452 case 0:
1453 _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
1454 _mod->setChannelVol(_id | 0x000, vol);
1455 break;
1456 case 1:
1457 _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
1458 _mod->setChannelVol(_id | 0x100, vol);
1459 break;
1460 }
1461 _loop = (_loop + 1) & 3;
1462 if (!_loop) {
1463 _curfreq += 4;
1464 if (_curfreq >= 0x01F4)
1465 return false;
1466 }
1467 return true;
1468 }
1469 private:
1470 const uint16 _offset;
1471 const uint16 _size;
1472
1473 uint16 _loop;
1474 uint16 _curfreq;
1475 };
1476
1477 // plays a series of double-looped sounds at varying frequencies and delays, very specialized
1478 // Guardian of the Sphinx, perhaps?
1479 class V2A_Sound_Special_Zak82 : public V2A_Sound_Base<4> {
1480 public:
V2A_Sound_Special_Zak82(uint16 offset,uint16 size)1481 V2A_Sound_Special_Zak82(uint16 offset, uint16 size) :
1482 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1483 virtual void start(Player_MOD *mod, int id, const byte *data) {
1484 _mod = mod;
1485 _id = id;
1486 _data = (char *)malloc(READ_LE_UINT16(data));
1487 memcpy(_data, data, READ_LE_UINT16(data));
1488
1489 // Wait values were to insure playing an integral number of loops on each sample
1490 // and have been adjusted to reflect the actual duration spent playing
1491 _loop = 0;
1492 _playctr = 240;
1493 _wait1 = 76; // was 39, extended to loop twice
1494 _wait2 = 10000;
1495 _wait3 = 10000;
1496 _wait4 = 10000;
1497
1498 int size = 2000;
1499 int offset = _offset;
1500 assert(offset + size <= _offset + _size);
1501 char *tmp_data = (char *)malloc(size);
1502 memcpy(tmp_data, _data + offset, size);
1503 _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0479, 0xFF, 0, size);
1504 }
update()1505 virtual bool update() {
1506 assert(_id);
1507 char *tmp_data1, *tmp_data2;
1508 int size, offset = _offset;
1509
1510 if (!--_wait1) {
1511 _wait1 = 10000;
1512 _mod->stopChannel(_id | 0x000);
1513 } else if (!--_wait2) {
1514 _wait2 = 10000;
1515 _mod->stopChannel(_id | 0x000);
1516 } else if (!--_wait3) {
1517 _wait3 = 10000;
1518 _mod->stopChannel(_id | 0x200);
1519 } else if (!--_wait4) {
1520 _wait4 = 10000;
1521 _mod->stopChannel(_id | 0x100);
1522 _mod->stopChannel(_id | 0x300);
1523 }
1524 if (--_playctr)
1525 return true;
1526
1527 switch (++_loop) {
1528 case 1:
1529 size = 6300;
1530 offset += 0x07D0;
1531 assert(offset + size <= _offset + _size);
1532 tmp_data1 = (char *)malloc(size);
1533 memcpy(tmp_data1, _data + offset, size);
1534 _mod->startChannel(_id | 0x000, tmp_data1, size, BASE_FREQUENCY / 0x0479, 0x7F, 0, size, -127);
1535 _wait2 = 241; // was 120, extended to loop twice
1536 _playctr = 10;
1537 break;
1538 case 2:
1539 size = 6292;
1540 offset += 0x206C;
1541 assert(offset + size <= _offset + _size);
1542 tmp_data1 = (char *)malloc(size);
1543 memcpy(tmp_data1, _data + offset, size);
1544 _mod->startChannel(_id | 0x200, tmp_data1, size, BASE_FREQUENCY / 0x0384, 0x7F, 0, size, 127);
1545 _wait3 = 189; // was 94, extended to loop twice
1546 _playctr = 20;
1547 break;
1548 case 3:
1549 size = 6300;
1550 offset += 0x07D0;
1551 assert(offset + size <= _offset + _size);
1552 tmp_data1 = (char *)malloc(size);
1553 tmp_data2 = (char *)malloc(size);
1554 memcpy(tmp_data1, _data + offset, size);
1555 memcpy(tmp_data2, _data + offset, size);
1556 _mod->startChannel(_id | 0x100, tmp_data1, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, 127);
1557 _mod->startChannel(_id | 0x300, tmp_data2, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, -127);
1558 _wait4 = 101; // was 50, extended to loop twice
1559 _playctr = 120;
1560 break;
1561 default:
1562 return false;
1563 }
1564 return true;
1565 }
1566 private:
1567 const uint16 _offset;
1568 const uint16 _size;
1569
1570 uint16 _loop;
1571 uint16 _playctr;
1572 uint16 _wait1;
1573 uint16 _wait2;
1574 uint16 _wait3;
1575 uint16 _wait4;
1576 };
1577
1578 // plays a "ding" (volume 0-max-0) followed by a sound sample, a pause, then loops again
1579 // Mars Tram about to depart
1580 class V2A_Sound_Special_Zak86 : public V2A_Sound_Base<1> {
1581 public:
V2A_Sound_Special_Zak86(uint16 offset,uint16 size)1582 V2A_Sound_Special_Zak86(uint16 offset, uint16 size) :
1583 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1584 virtual void start(Player_MOD *mod, int id, const byte *data) {
1585 _mod = mod;
1586 _id = id;
1587 _data = (char *)malloc(READ_LE_UINT16(data));
1588 memcpy(_data, data, READ_LE_UINT16(data));
1589
1590 _mode = 0;
1591 _vol = 0;
1592 _volmod = 16;
1593
1594 int size = 32;
1595 int offset = _offset + 0x2B8E;
1596 assert(offset + size <= _offset + _size);
1597 char *tmp_data = (char *)malloc(size);
1598 memcpy(tmp_data, _data + offset, size);
1599 _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
1600 }
update()1601 virtual bool update() {
1602 assert(_id);
1603 int size, offset;
1604 char *tmp_data;
1605
1606 switch (_mode) {
1607 case 0:
1608 _mod->setChannelVol(_id | 0x000, (_vol << 2) | (_vol >> 4));
1609 if (_vol + _volmod > 0) {
1610 _vol += _volmod;
1611 if (_vol > 0x3F) {
1612 _vol = 0x3F;
1613 _volmod = -4;
1614 }
1615 return true;
1616 }
1617 _mod->stopChannel(_id | 0x000);
1618 _mode = 1;
1619
1620 size = 0x2B8E;
1621 offset = _offset;
1622 assert(offset + size <= _offset + _size);
1623 tmp_data = (char *)malloc(size);
1624 memcpy(tmp_data, _data + offset, size);
1625 _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0152, 0x3F);
1626 _volmod = 100;
1627 break;
1628 case 1:
1629 if (!--_volmod) {
1630 size = 32;
1631 offset = _offset + 0x2B8E;
1632 assert(offset + size <= _offset + _size);
1633 tmp_data = (char *)malloc(size);
1634 memcpy(tmp_data, _data + offset, size);
1635 _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
1636 _mode = 0;
1637 _vol = 0;
1638 _volmod = 16;
1639 }
1640 break;
1641 }
1642 return true;
1643 }
1644 private:
1645 const uint16 _offset;
1646 const uint16 _size;
1647
1648 uint16 _mode;
1649 uint16 _vol;
1650 int16 _volmod;
1651 };
1652
1653 // modulates volume on 4 samples, frequency on only 2 of them
1654 // Skolarian device pedestal activated without any parts
1655 class V2A_Sound_Special_Zak98 : public V2A_Sound_Base<4> {
1656 public:
V2A_Sound_Special_Zak98(uint16 offset,uint16 size)1657 V2A_Sound_Special_Zak98(uint16 offset, uint16 size) :
1658 _offset(offset), _size(size) { }
start(Player_MOD * mod,int id,const byte * data)1659 virtual void start(Player_MOD *mod, int id, const byte *data) {
1660 _mod = mod;
1661 _id = id;
1662 _data = (char *)malloc(READ_LE_UINT16(data));
1663 memcpy(_data, data, READ_LE_UINT16(data));
1664
1665 _freq[0] = 0x1E0;
1666 _freq[1] = 0x3E8;
1667 _freq[2] = 0x200;
1668 _freq[3] = 0x408;
1669 _vol[0] = 0x3F;
1670 _vol[1] = 0x3F;
1671 _vol[2] = 0x3F;
1672 _vol[3] = 0x3F;
1673 _freqmod = 4;
1674 _volmod[0] = -2;
1675 _volmod[1] = -1;
1676
1677 char *tmp_data1 = (char *)malloc(_size);
1678 char *tmp_data2 = (char *)malloc(_size);
1679 char *tmp_data3 = (char *)malloc(_size);
1680 char *tmp_data4 = (char *)malloc(_size);
1681 memcpy(tmp_data1, _data + _offset, _size);
1682 memcpy(tmp_data2, _data + _offset, _size);
1683 memcpy(tmp_data3, _data + _offset, _size);
1684 memcpy(tmp_data4, _data + _offset, _size);
1685 _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq[0], _vol[0], 0, _size, -127);
1686 _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq[1], _vol[1], 0, _size, 127);
1687 _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq[2], _vol[2], 0, _size, 127);
1688 _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq[3], _vol[3], 0, _size, -127);
1689 }
update()1690 virtual bool update() {
1691 assert(_id);
1692 const uint16 _minvol[2] = {0x2E, 0x32};
1693 int i;
1694 for (i = 0; i < 4; i++) {
1695 _mod->setChannelFreq(_id | (i << 8), BASE_FREQUENCY / _freq[i]);
1696 _mod->setChannelVol(_id | (i << 8), _vol[i]);
1697 }
1698 for (i = 0; i < 2; i++) {
1699 _vol[i] += _volmod[i];
1700 if (_vol[i] > 0x3F) {
1701 _vol[i] = 0x3F;
1702 _volmod[i] = -_volmod[i];
1703 } else if (_vol[i] < _minvol[i]) {
1704 _vol[i] = _minvol[i];
1705 _volmod[i] = -_volmod[i];
1706 }
1707 _vol[i + 2] = _vol[i];
1708 }
1709 _freq[0] += _freqmod;
1710 if (_freq[0] > 0x2BC) {
1711 _freq[0] = 0x2BC;
1712 _freqmod = -_freqmod;
1713 } else if (_freq[0] < 0x1E0) {
1714 _freq[0] = 0x1E0;
1715 _freqmod = -_freqmod;
1716 }
1717 _freq[2] = _freq[0] + 0x20;
1718 return true;
1719 }
1720 private:
1721 const uint16 _offset;
1722 const uint16 _size;
1723
1724 uint16 _freq[4];
1725 uint16 _vol[4];
1726 int16 _freqmod;
1727 int16 _volmod[2];
1728 };
1729
1730 #define CRCToSound(CRC, SOUND) \
1731 if (crc == CRC) \
1732 return new SOUND
1733
findSound(unsigned long crc)1734 static V2A_Sound *findSound(unsigned long crc) {
1735 CRCToSound(0x8FAB08C4, V2A_Sound_SingleLooped(0x006C, 0x2B58, 0x016E, 0x3F)); // Maniac 17
1736 CRCToSound(0xB673160A, V2A_Sound_SingleLooped(0x006C, 0x1E78, 0x01C2, 0x1E)); // Maniac 38
1737 CRCToSound(0x4DB1D0B2, V2A_Sound_MultiLooped(0x0072, 0x1BC8, 0x023D, 0x3F, 0x0224, 0x3F)); // Maniac 20
1738 CRCToSound(0x754D75EF, V2A_Sound_Single(0x0076, 0x0738, 0x01FC, 0x3F)); // Maniac 10
1739 CRCToSound(0x6E3454AF, V2A_Sound_Single(0x0076, 0x050A, 0x017C, 0x3F)); // Maniac 12
1740 CRCToSound(0x92F0BBB6, V2A_Sound_Single(0x0076, 0x3288, 0x012E, 0x3F)); // Maniac 41
1741 CRCToSound(0xE1B13982, V2A_Sound_MultiLoopedDuration(0x0078, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x001E)); // Maniac 21
1742 CRCToSound(0x288B16CF, V2A_Sound_MultiLoopedDuration(0x007A, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x000A)); // Maniac 11
1743 CRCToSound(0xA7565268, V2A_Sound_MultiLoopedDuration(0x007A, 0x0040, 0x00F8, 0x3F, 0x00F7, 0x3F, 0x000A)); // Maniac 19
1744 CRCToSound(0x7D419BFC, V2A_Sound_MultiLoopedDuration(0x007E, 0x0040, 0x012C, 0x3F, 0x0149, 0x3F, 0x001E)); // Maniac 22
1745 CRCToSound(0x1B52280C, V2A_Sound_Single(0x0098, 0x0A58, 0x007F, 0x32)); // Maniac 6
1746 CRCToSound(0x38D4A810, V2A_Sound_Single(0x0098, 0x2F3C, 0x0258, 0x32)); // Maniac 7
1747 CRCToSound(0x09F98FC2, V2A_Sound_Single(0x0098, 0x0A56, 0x012C, 0x32)); // Maniac 16
1748 CRCToSound(0x90440A65, V2A_Sound_Single(0x0098, 0x0208, 0x0078, 0x28)); // Maniac 28
1749 CRCToSound(0x985C76EF, V2A_Sound_Single(0x0098, 0x0D6E, 0x00C8, 0x32)); // Maniac 30
1750 CRCToSound(0x76156137, V2A_Sound_Single(0x0098, 0x2610, 0x017C, 0x39)); // Maniac 39
1751 CRCToSound(0x5D95F88C, V2A_Sound_Single(0x0098, 0x0A58, 0x007F, 0x1E)); // Maniac 65
1752 CRCToSound(0x92D704EA, V2A_Sound_SingleLooped(0x009C, 0x29BC, 0x012C, 0x3F, 0x1BD4, 0x0DE8)); // Maniac 15
1753 CRCToSound(0x92F5513C, V2A_Sound_Single(0x009E, 0x0DD4, 0x01F4, 0x3F)); // Maniac 13
1754 CRCToSound(0xCC2F3B5A, V2A_Sound_Single(0x009E, 0x00DE, 0x01AC, 0x3F)); // Maniac 43
1755 CRCToSound(0x153207D3, V2A_Sound_Single(0x009E, 0x0E06, 0x02A8, 0x3F)); // Maniac 67
1756 CRCToSound(0xC4F370CE, V2A_Sound_Single(0x00AE, 0x0330, 0x01AC, 0x3F)); // Maniac 8
1757 CRCToSound(0x928C4BAC, V2A_Sound_Single(0x00AE, 0x08D6, 0x01AC, 0x3F)); // Maniac 9
1758 CRCToSound(0x62D5B11F, V2A_Sound_Single(0x00AE, 0x165C, 0x01CB, 0x3F)); // Maniac 27
1759 CRCToSound(0x3AB22CB5, V2A_Sound_Single(0x00AE, 0x294E, 0x012A, 0x3F)); // Maniac 62
1760 CRCToSound(0x2D70BBE9, V2A_Sound_SingleLoopedPitchbend(0x00B4, 0x1702, 0x03E8, 0x0190, 0x3F, 5)); // Maniac 64
1761 CRCToSound(0xFA4C1B1C, V2A_Sound_Special_Maniac69(0x00B2, 0x1702, 0x0190, 0x3F)); // Maniac 69
1762 CRCToSound(0x19D50D67, V2A_Sound_Special_ManiacDing(0x00B6, 0x0020, 0x00C8, 16, 2)); // Maniac 14
1763 CRCToSound(0x3E6FBE15, V2A_Sound_Special_ManiacTentacle(0x00B2, 0x0010, 0x007C, 0x016D, 1)); // Maniac 25
1764 CRCToSound(0x5305753C, V2A_Sound_Special_ManiacTentacle(0x00B2, 0x0010, 0x007C, 0x016D, 7)); // Maniac 36
1765 CRCToSound(0x28895106, V2A_Sound_Special_Maniac59(0x00C0, 0x00FE, 0x00E9, 0x0111, 4, 0x0A)); // Maniac 59
1766 CRCToSound(0xB641ACF6, V2A_Sound_Special_Maniac61(0x00C8, 0x0100, 0x00C8, 0x01C2)); // Maniac 61
1767 CRCToSound(0xE1A91583, V2A_Sound_Special_ManiacPhone(0x00D0, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x3C, 5, 6)); // Maniac 23
1768 CRCToSound(0x64816ED5, V2A_Sound_Special_ManiacPhone(0x00D0, 0x0040, 0x00BE, 0x37, 0x00BD, 0x37, 0x3C, 5, 6)); // Maniac 24
1769 CRCToSound(0x639D72C2, V2A_Sound_Special_Maniac46(0x00D0, 0x10A4, 0x0080, 0x3F, 0x28, 3)); // Maniac 46
1770 CRCToSound(0xE8826D92, V2A_Sound_Special_ManiacTypewriter(0x00EC, 0x025A, 0x023C, 0x3F, 8, (const uint8 *)"\x20\x41\x04\x21\x08\x10\x13\x07", true)); // Maniac 45
1771 CRCToSound(0xEDFF3D41, V2A_Sound_Single(0x00F8, 0x2ADE, 0x01F8, 0x3F)); // Maniac 42 (this should echo, but it's barely noticeable and I don't feel like doing it)
1772 CRCToSound(0x15606D06, V2A_Sound_Special_Maniac32(0x0148, 0x0020, 0x0168, 0x0020, 0x3F)); // Maniac 32
1773 CRCToSound(0x753EAFE3, V2A_Sound_Special_Maniac44(0x017C, 0x0010, 0x018C, 0x0020, 0x00C8, 0x0080, 0x3F)); // Maniac 44
1774 CRCToSound(0xB1AB065C, V2A_Sound_Music(0x0032, 0x00B2, 0x08B2, 0x1222, 0x1A52, 0x23C2, 0x3074, false)); // Maniac 50
1775 CRCToSound(0x091F5D9C, V2A_Sound_Music(0x0032, 0x0132, 0x0932, 0x1802, 0x23D2, 0x3EA2, 0x4F04, false)); // Maniac 58
1776
1777 CRCToSound(0x8E2C8AB3, V2A_Sound_SingleLooped(0x005C, 0x0F26, 0x0168, 0x3C)); // Zak 41
1778 CRCToSound(0x3792071F, V2A_Sound_SingleLooped(0x0060, 0x1A18, 0x06A4, 0x3F)); // Zak 88
1779 CRCToSound(0xF192EDE9, V2A_Sound_SingleLooped(0x0062, 0x0054, 0x01FC, 0x1E)); // Zak 68
1780 CRCToSound(0xC43B0245, V2A_Sound_Special_Zak70(0x006C, 0x166E, 0x00C8, 0x0190, 0x0320, 0x0640, 0x32)); // Zak 70
1781 CRCToSound(0xCEB51670, V2A_Sound_SingleLooped(0x00AC, 0x26DC, 0x012C, 0x3F)); // Zak 42
1782 CRCToSound(0x10347B51, V2A_Sound_SingleLooped(0x006C, 0x00E0, 0x0594, 0x3F)); // Zak 18
1783 CRCToSound(0x9D2FADC0, V2A_Sound_MultiLooped(0x0072, 0x1FC8, 0x016A, 0x3F, 0x01CE, 0x3F)); // Zak 80
1784 CRCToSound(0xFAD2C676, V2A_Sound_MultiLooped(0x0076, 0x0010, 0x0080, 0x3F, 0x0090, 0x3B)); // Zak 40
1785 CRCToSound(0x01508B48, V2A_Sound_Single(0x0076, 0x0D8C, 0x017C, 0x3F)); // Zak 90
1786 CRCToSound(0x9C18DC46, V2A_Sound_Single(0x0076, 0x0D8C, 0x015E, 0x3F)); // Zak 91
1787 CRCToSound(0xF98F7EAC, V2A_Sound_Single(0x0076, 0x0D8C, 0x0140, 0x3F)); // Zak 92
1788 CRCToSound(0xC925FBEF, V2A_Sound_MultiLoopedDuration(0x0080, 0x0010, 0x0080, 0x3F, 0x0090, 0x3B, 0x0168)); // Zak 53
1789 CRCToSound(0xCAB35257, V2A_Sound_Special_Zak101(0x00DA, 0x425C, 0x023C, 0x08F0, 0x0640, 0x0478, 0x3F, 0x012C)); // Zak 101
1790 CRCToSound(0xA31FE4FD, V2A_Sound_Single(0x0094, 0x036A, 0x00E1, 0x3F)); // Zak 97
1791 CRCToSound(0x0A1AE0F5, V2A_Sound_Single(0x009E, 0x0876, 0x0168, 0x3F)); // Zak 5
1792 CRCToSound(0xD01A66CB, V2A_Sound_Single(0x009E, 0x04A8, 0x0168, 0x3F)); // Zak 47
1793 CRCToSound(0x5497B912, V2A_Sound_Single(0x009E, 0x0198, 0x01F4, 0x3F)); // Zak 39
1794 CRCToSound(0x2B50362F, V2A_Sound_Single(0x009E, 0x09B6, 0x023D, 0x3F)); // Zak 67
1795 CRCToSound(0x7BFB6E72, V2A_Sound_Single(0x009E, 0x0D14, 0x0078, 0x3F)); // Zak 69
1796 CRCToSound(0xB803A792, V2A_Sound_Single(0x009E, 0x2302, 0x02BC, 0x3F)); // Zak 78
1797 CRCToSound(0x7AB82E39, V2A_Sound_SingleLooped(0x00A0, 0x2A3C, 0x016E, 0x3F, 0x1018, 0x1A24)); // Zak 100
1798 CRCToSound(0x28057CEC, V2A_Sound_Single(0x0098, 0x0FEC, 0x0140, 0x32)); // Zak 63
1799 CRCToSound(0x1180A2FC, V2A_Sound_Single(0x0098, 0x0F06, 0x0190, 0x32)); // Zak 64
1800 CRCToSound(0x12616755, V2A_Sound_Single(0x0098, 0x14C8, 0x023C, 0x14)); // Zak 9
1801 CRCToSound(0x642723AA, V2A_Sound_Special_Zak37(0x00A2, 0x1702, 0x01F4, 0x3F)); // Zak 37
1802 CRCToSound(0xDEE56848, V2A_Sound_Single(0x009A, 0x0F86, 0x0100, 0x3F)); // Zak 93
1803 CRCToSound(0xF9BE27B8, V2A_Sound_Special_Zak37(0x011C, 0x1704, 0x0228, 0x3F)); // Zak 113
1804 CRCToSound(0xC73487B2, V2A_Sound_Single(0x00B0, 0x18BA, 0x0478, 0x3F)); // Zak 81
1805 CRCToSound(0x32D8F925, V2A_Sound_Single(0x00B0, 0x2E46, 0x00F0, 0x3F)); // Zak 94
1806 CRCToSound(0x988C83A5, V2A_Sound_Single(0x00B0, 0x0DE0, 0x025B, 0x3F)); // Zak 106
1807 CRCToSound(0x8F1E3B3D, V2A_Sound_Single(0x00B0, 0x05FE, 0x04E2, 0x3F)); // Zak 107
1808 CRCToSound(0x0A2A7646, V2A_Sound_Single(0x00B0, 0x36FE, 0x016E, 0x3F)); // Zak 43
1809 CRCToSound(0x6F1FC435, V2A_Sound_Single(0x00B0, 0x2808, 0x044C, 0x3F)); // Zak 108
1810 CRCToSound(0x870EFC29, V2A_Sound_SingleLoopedPitchbend(0x00BA, 0x0100, 0x03E8, 0x00C8, 0x3F, 3)); // Zak 55
1811 CRCToSound(0xED773699, V2A_Sound_Special_ManiacDing(0x00B4, 0x0020, 0x012C, 8, 4)); // Zak 3
1812 CRCToSound(0x0BF59774, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00F8, 0x00F7, 8, 1)); // Zak 72
1813 CRCToSound(0x656FFEDE, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00C4, 0x00C3, 8, 1)); // Zak 73
1814 CRCToSound(0xFC4D41E5, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00A5, 0x00A4, 8, 1)); // Zak 74
1815 CRCToSound(0xC0DD2089, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x009C, 0x009B, 8, 1)); // Zak 75
1816 CRCToSound(0x627DFD92, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x008B, 0x008A, 8, 1)); // Zak 76
1817 CRCToSound(0x703E05C1, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x007C, 0x007B, 8, 1)); // Zak 77
1818 CRCToSound(0xB0F77006, V2A_Sound_Special_Zak52(0x00B0, 0x01BC)); // Zak 52
1819 CRCToSound(0x5AE9D6A7, V2A_Sound_Special_ZakAirplane(0x00CA, 0x22A4, 0x0113, 0x0227)); // Zak 109
1820 CRCToSound(0xABE0D3B0, V2A_Sound_Special_ZakAirplane(0x00CE, 0x22A4, 0x0227, 0x0113)); // Zak 105
1821 CRCToSound(0x788CC749, V2A_Sound_Special_Zak71(0x00C8, 0x0B37)); // Zak 71
1822 CRCToSound(0x2E2AB1FA, V2A_Sound_Special_Zak99(0x00D4, 0x04F0, 0x0FE3, 0x0080, 0x3F)); // Zak 99
1823 CRCToSound(0x1304CF20, V2A_Sound_Special_ManiacTypewriter(0x00DC, 0x0624, 0x023C, 0x3C, 2, (const uint8 *)"\x14\x11", false)); // Zak 79
1824 CRCToSound(0xAE68ED91, V2A_Sound_Special_Zak54(0x00D4, 0x1A25, 0x1E1E, 0x0B80, 0x01F4)); // Zak 54
1825 CRCToSound(0xA4F40F97, V2A_Sound_Special_Zak61(0x00E4, 0x0020)); // Zak 61
1826 CRCToSound(0x348F85CE, V2A_Sound_Special_Zak62(0x00E4, 0x0020)); // Zak 62
1827 CRCToSound(0xD473AB86, V2A_Sound_Special_ManiacTypewriter(0x0122, 0x03E8, 0x00BE, 0x3F, 7, (const uint8 *)"\x0F\x0B\x04\x0F\x1E\x0F\x66", false)); // Zak 46
1828 CRCToSound(0x84A0BA90, V2A_Sound_Special_Zak110(0x0126, 0x0040, 0x0136, 0x0080, 0x007C, 0x0087)); // Zak 110
1829 CRCToSound(0x92680D9F, V2A_Sound_Special_Zak32(0x0140, 0x0150, 0x0010, 0x0010)); // Zak 32
1830 CRCToSound(0xABFFDB02, V2A_Sound_Special_Zak86(0x01A2, 0x2BAE)); // Zak 86
1831 CRCToSound(0x41045447, V2A_Sound_Special_Zak98(0x017A, 0x0020)); // Zak 98
1832 CRCToSound(0xC8EEBD34, V2A_Sound_Special_Zak82(0x01A6, 0x3900)); // Zak 82
1833 CRCToSound(0x42F9469F, V2A_Sound_Music(0x05F6, 0x0636, 0x0456, 0x0516, 0x05D6, 0x05E6, 0x0A36, true)); // Zak 96
1834 CRCToSound(0x038BBD78, V2A_Sound_Music(0x054E, 0x05CE, 0x044E, 0x04BE, 0x052E, 0x053E, 0x0BCE, true)); // Zak 85
1835 CRCToSound(0x06FFADC5, V2A_Sound_Music(0x0626, 0x0686, 0x0446, 0x04F6, 0x0606, 0x0616, 0x0C86, true)); // Zak 87
1836 CRCToSound(0xCE20ECF0, V2A_Sound_Music(0x0636, 0x0696, 0x0446, 0x0576, 0x0616, 0x0626, 0x0E96, true)); // Zak 114
1837 CRCToSound(0xBDA01BB6, V2A_Sound_Music(0x0678, 0x06B8, 0x0458, 0x0648, 0x0658, 0x0668, 0x0EB8, false)); // Zak 33
1838 CRCToSound(0x59976529, V2A_Sound_Music(0x088E, 0x092E, 0x048E, 0x05EE, 0x074E, 0x07EE, 0x112E, true)); // Zak 49
1839 CRCToSound(0xED1EED02, V2A_Sound_Music(0x08D0, 0x0950, 0x0440, 0x07E0, 0x08B0, 0x08C0, 0x1350, false)); // Zak 112
1840 CRCToSound(0x5A16C037, V2A_Sound_Music(0x634A, 0x64CA, 0x049A, 0x18FA, 0x398A, 0x511A, 0x6CCA, false)); // Zak 95
1841 return NULL;
1842 }
1843
Player_V2A(ScummEngine * scumm,Audio::Mixer * mixer)1844 Player_V2A::Player_V2A(ScummEngine *scumm, Audio::Mixer *mixer) {
1845 int i;
1846 _vm = scumm;
1847
1848 InitCRC();
1849
1850 for (i = 0; i < V2A_MAXSLOTS; i++) {
1851 _slot[i].id = 0;
1852 _slot[i].sound = NULL;
1853 }
1854
1855 _mod = new Player_MOD(mixer);
1856 _mod->setUpdateProc(update_proc, this, 60);
1857 }
1858
~Player_V2A()1859 Player_V2A::~Player_V2A() {
1860 delete _mod;
1861 }
1862
setMusicVolume(int vol)1863 void Player_V2A::setMusicVolume(int vol) {
1864 _mod->setMusicVolume(vol);
1865 }
1866
getSoundSlot(int id) const1867 int Player_V2A::getSoundSlot(int id) const {
1868 int i;
1869 for (i = 0; i < V2A_MAXSLOTS; i++) {
1870 if (_slot[i].id == id)
1871 break;
1872 }
1873 if (i == V2A_MAXSLOTS) {
1874 if (id == 0)
1875 warning("player_v2a - out of sound slots");
1876 return -1;
1877 }
1878 return i;
1879 }
1880
stopAllSounds()1881 void Player_V2A::stopAllSounds() {
1882 for (int i = 0; i < V2A_MAXSLOTS; i++) {
1883 if (!_slot[i].id)
1884 continue;
1885 _slot[i].sound->stop();
1886 delete _slot[i].sound;
1887 _slot[i].sound = NULL;
1888 _slot[i].id = 0;
1889 }
1890 }
1891
stopSound(int nr)1892 void Player_V2A::stopSound(int nr) {
1893 int i;
1894 if (nr == 0)
1895 return;
1896 i = getSoundSlot(nr);
1897 if (i == -1)
1898 return;
1899 _slot[i].sound->stop();
1900 delete _slot[i].sound;
1901 _slot[i].sound = NULL;
1902 _slot[i].id = 0;
1903 }
1904
startSound(int nr)1905 void Player_V2A::startSound(int nr) {
1906 assert(_vm);
1907 byte *data = _vm->getResourceAddress(rtSound, nr);
1908 assert(data);
1909 uint32 crc = GetCRC(data + 0x0A, READ_BE_UINT16(data + 0x08));
1910 V2A_Sound *snd = findSound(crc);
1911 if (snd == NULL) {
1912 warning("player_v2a - sound %i not recognized yet (crc %08X)", nr, crc);
1913 return;
1914 }
1915 stopSound(nr);
1916 int i = getSoundSlot();
1917 if (i == -1) {
1918 delete snd;
1919 return;
1920 }
1921 _slot[i].id = nr;
1922 _slot[i].sound = snd;
1923 _slot[i].sound->start(_mod, nr, data);
1924 }
1925
update_proc(void * param)1926 void Player_V2A::update_proc(void *param) {
1927 ((Player_V2A *)param)->updateSound();
1928 }
1929
updateSound()1930 void Player_V2A::updateSound() {
1931 int i;
1932 for (i = 0; i < V2A_MAXSLOTS; i++) {
1933 if ((_slot[i].id) && (!_slot[i].sound->update())) {
1934 _slot[i].sound->stop();
1935 delete _slot[i].sound;
1936 _slot[i].sound = NULL;
1937 _slot[i].id = 0;
1938 }
1939 }
1940 }
1941
getMusicTimer()1942 int Player_V2A::getMusicTimer() {
1943 return 0; // FIXME - need to keep track of playing music resources
1944 }
1945
getSoundStatus(int nr) const1946 int Player_V2A::getSoundStatus(int nr) const {
1947 for (int i = 0; i < V2A_MAXSLOTS; i++) {
1948 if (_slot[i].id == nr)
1949 return 1;
1950 }
1951 return 0;
1952 }
1953
1954 } // End of namespace Scumm
1955