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