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 
24 #include "engines/engine.h"
25 #include "scumm/players/player_v1.h"
26 #include "scumm/scumm.h"
27 
28 namespace Scumm {
29 
30 #define FB_WNOISE 0x12000       /* feedback for white noise */
31 #define FB_PNOISE 0x08000       /* feedback for periodic noise */
32 
33 #define TIMER_BASE_FREQ 1193000
34 #define FIXP_SHIFT  16
35 
Player_V1(ScummEngine * scumm,Audio::Mixer * mixer,bool pcjr)36 Player_V1::Player_V1(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr)
37 	: Player_V2(scumm, mixer, pcjr) {
38 	// Initialize channel code
39 	for (int i = 0; i < 4; ++i)
40 		clear_channel(i);
41 
42 	_mplex_step = (_sampleRate << FIXP_SHIFT) / 1193000;
43 	_next_chunk = _repeat_chunk = 0;
44 	_forced_level = 0;
45 	_random_lsr = 0;
46 }
47 
~Player_V1()48 Player_V1::~Player_V1() {
49 }
50 
chainSound(int nr,byte * data)51 void Player_V1::chainSound(int nr, byte *data) {
52 	uint i;
53 	for (i = 0; i < 4; ++i)
54 		clear_channel(i);
55 
56 	_current_nr = nr;
57 	_current_data = data;
58 	_repeat_chunk = _next_chunk = data + (_pcjr ? 2 : 4);
59 
60 	debug(4, "Chaining new sound %d", nr);
61 	if (_pcjr)
62 		parsePCjrChunk();
63 	else
64 		parseSpeakerChunk();
65 }
66 
startSound(int nr)67 void Player_V1::startSound(int nr) {
68 	Common::StackLock lock(_mutex);
69 
70 	byte *data = _vm->getResourceAddress(rtSound, nr);
71 	assert(data);
72 
73 	int offset = _pcjr ? READ_LE_UINT16(data+4) : 6;
74 	int cprio = _current_data ? *(_current_data) & 0x7f : 0;
75 	int prio  = *(data + offset) & 0x7f;
76 	int restartable = *(data + offset) & 0x80;
77 
78 	debug(4, "startSound %d: prio %d%s, cprio %d",
79 		  nr, prio, restartable ? " restartable" : "", cprio);
80 
81 	if (!_current_nr || cprio <= prio) {
82 		if (_current_data && (*(_current_data) & 0x80)) {
83 			_next_nr = _current_nr;
84 			_next_data = _current_data;
85 		}
86 
87 		chainSound(nr, data + offset);
88 	}
89 }
90 
stopAllSounds()91 void Player_V1::stopAllSounds() {
92 	Common::StackLock lock(_mutex);
93 
94 	for (int i = 0; i < 4; i++)
95 		clear_channel(i);
96 	_repeat_chunk = _next_chunk = 0;
97 	_next_nr = _current_nr = 0;
98 	_next_data = _current_data = 0;
99 }
100 
stopSound(int nr)101 void Player_V1::stopSound(int nr) {
102 	Common::StackLock lock(_mutex);
103 
104 	if (_next_nr == nr) {
105 		_next_nr = 0;
106 		_next_data = 0;
107 	}
108 	if (_current_nr == nr) {
109 		for (int i = 0; i < 4; i++) {
110 			clear_channel(i);
111 		}
112 		_repeat_chunk = _next_chunk = 0;
113 		_current_nr = 0;
114 		_current_data = 0;
115 		chainNextSound();
116 	}
117 }
118 
clear_channel(int i)119 void Player_V1::clear_channel(int i) {
120 	_channels[i].freq   = 0;
121 	_channels[i].volume = 15;
122 }
123 
getMusicTimer()124 int Player_V1::getMusicTimer() {
125 	/* Do V1 games have a music timer? */
126 	return 0;
127 }
128 
parseSpeakerChunk()129 void Player_V1::parseSpeakerChunk() {
130 	set_mplex(3000);
131 	_forced_level = 0;
132 
133  parse_again:
134 	_chunk_type = READ_LE_UINT16(_next_chunk);
135 	debug(6, "parseSpeakerChunk: sound %d, offset %lx, chunk %x",
136 			_current_nr, (long)(_next_chunk - _current_data), _chunk_type);
137 
138 	_next_chunk += 2;
139 	switch (_chunk_type) {
140 	case 0xffff:
141 		_current_nr = 0;
142 		_current_data = 0;
143 		_channels[0].freq = 0;
144 		_next_chunk = 0;
145 		chainNextSound();
146 		break;
147 	case 0xfffe:
148 		_repeat_chunk = _next_chunk;
149 		goto parse_again;
150 
151 	case 0xfffd:
152 		_next_chunk = _repeat_chunk;
153 		goto parse_again;
154 
155 	case 0xfffc:
156 		/* handle reset. We don't need this do we? */
157 		goto parse_again;
158 
159 	case 0:
160 		_time_left = 1;
161 		set_mplex(READ_LE_UINT16(_next_chunk));
162 		_next_chunk += 2;
163 		break;
164 	case 1:
165 		set_mplex(READ_LE_UINT16(_next_chunk));
166 		_start = READ_LE_UINT16(_next_chunk + 2);
167 		_end   = READ_LE_UINT16(_next_chunk + 4);
168 		_delta = (int16) READ_LE_UINT16(_next_chunk + 6);
169 		_repeat_ctr = READ_LE_UINT16(_next_chunk + 8);
170 		_channels[0].freq = _start;
171 		_next_chunk += 10;
172 		debug(6, "chunk 1: mplex %d, freq %d -> %d step %d  x %d",
173 				_mplex, _start, _end, _delta, _repeat_ctr);
174 		break;
175 	case 2:
176 		_start = READ_LE_UINT16(_next_chunk);
177 		_end   = READ_LE_UINT16(_next_chunk + 2);
178 		_delta = (int16) READ_LE_UINT16(_next_chunk + 4);
179 		_channels[0].freq = 0;
180 		_next_chunk += 6;
181 		_forced_level = -1;
182 		debug(6, "chunk 2: %d -> %d step %d",
183 				_start, _end, _delta);
184 		break;
185 	case 3:
186 		_start = READ_LE_UINT16(_next_chunk);
187 		_end   = READ_LE_UINT16(_next_chunk + 2);
188 		_delta = (int16) READ_LE_UINT16(_next_chunk + 4);
189 		_channels[0].freq = 0;
190 		_next_chunk += 6;
191 		_forced_level = -1;
192 		debug(6, "chunk 3: %d -> %d step %d",
193 				_start, _end, _delta);
194 		break;
195 	}
196 }
197 
nextSpeakerCmd()198 void Player_V1::nextSpeakerCmd() {
199 	uint16 lsr;
200 	switch (_chunk_type) {
201 	case 0:
202 		if (--_time_left)
203 			return;
204 		_time_left = READ_LE_UINT16(_next_chunk);
205 		_next_chunk += 2;
206 		if (_time_left == 0xfffb) {
207 			/* handle 0xfffb?? */
208 			_time_left = READ_LE_UINT16(_next_chunk);
209 			_next_chunk += 2;
210 		}
211 		debug(7, "nextSpeakerCmd: chunk %d, offset %4lx: notelen %d",
212 				_chunk_type, (long)(_next_chunk - 2 - _current_data), _time_left);
213 		if (_time_left == 0) {
214 			parseSpeakerChunk();
215 		} else {
216 			_channels[0].freq = READ_LE_UINT16(_next_chunk);
217 			_next_chunk += 2;
218 			debug(7, "freq_current: %d", _channels[0].freq);
219 		}
220 		break;
221 
222 	case 1:
223 		_channels[0].freq = (_channels[0].freq + _delta) & 0xffff;
224 		if (_channels[0].freq == _end) {
225 			if (!--_repeat_ctr) {
226 				parseSpeakerChunk();
227 				return;
228 			}
229 			_channels[0].freq = _start;
230 		}
231 		break;
232 
233 	case 2:
234 		_start = (_start + _delta) & 0xffff;
235 		if (_start == _end) {
236 			parseSpeakerChunk();
237 			return;
238 		}
239 		set_mplex(_start);
240 		_forced_level = -_forced_level;
241 		break;
242 	case 3:
243 		_start = (_start + _delta) & 0xffff;
244 		if (_start == _end) {
245 			parseSpeakerChunk();
246 			return;
247 		}
248 		lsr = _random_lsr + 0x9248;
249 		lsr = (lsr >> 3) | (lsr << 13);
250 		_random_lsr = lsr;
251 		set_mplex((_start & lsr) | 0x180);
252 		_forced_level = -_forced_level;
253 		break;
254 	}
255 }
256 
parsePCjrChunk()257 void Player_V1::parsePCjrChunk() {
258 	uint tmp;
259 	uint i;
260 
261 	set_mplex(3000);
262 	_forced_level = 0;
263 
264 parse_again:
265 
266 	_chunk_type = READ_LE_UINT16(_next_chunk);
267 	debug(6, "parsePCjrChunk: sound %d, offset %4lx, chunk %x",
268 		  _current_nr, (long)(_next_chunk - _current_data), _chunk_type);
269 
270 	_next_chunk += 2;
271 	switch (_chunk_type) {
272 	case 0xffff:
273 		for (i = 0; i < 4; ++i)
274 			clear_channel(i);
275 		_current_nr = 0;
276 		_current_data = 0;
277 		_repeat_chunk = _next_chunk = 0;
278 		chainNextSound();
279 		break;
280 
281 	case 0xfffe:
282 		_repeat_chunk = _next_chunk;
283 		goto parse_again;
284 
285 	case 0xfffd:
286 		_next_chunk = _repeat_chunk;
287 		goto parse_again;
288 
289 	case 0xfffc:
290 		/* handle reset. We don't need this do we? */
291 		goto parse_again;
292 
293 	case 0:
294 		set_mplex(READ_LE_UINT16(_next_chunk));
295 		_next_chunk += 2;
296 		for (i = 0; i < 4; i++) {
297 			tmp = READ_LE_UINT16(_next_chunk);
298 			_next_chunk += 2;
299 			if (tmp == 0xffff) {
300 				_channels[i].cmd_ptr = 0;
301 				continue;
302 			}
303 			_channels[i].attack    = READ_LE_UINT16(_current_data + tmp);
304 			_channels[i].decay     = READ_LE_UINT16(_current_data + tmp + 2);
305 			_channels[i].level     = READ_LE_UINT16(_current_data + tmp + 4);
306 			_channels[i].sustain_1 = READ_LE_UINT16(_current_data + tmp + 6);
307 			_channels[i].sustain_2 = READ_LE_UINT16(_current_data + tmp + 8);
308 			_channels[i].notelen   = 1;
309 			_channels[i].volume    = 15;
310 			_channels[i].cmd_ptr   = _current_data + tmp + 10;
311 		}
312 		break;
313 
314 	case 1:
315 		set_mplex(READ_LE_UINT16(_next_chunk));
316 		tmp = READ_LE_UINT16(_next_chunk + 2);
317 		_channels[0].cmd_ptr = tmp != 0xffff ? _current_data + tmp : NULL;
318 		tmp = READ_LE_UINT16(_next_chunk + 4);
319 		_start = READ_LE_UINT16(_next_chunk + 6);
320 		_delta = (int16) READ_LE_UINT16(_next_chunk + 8);
321 		_time_left = READ_LE_UINT16(_next_chunk + 10);
322 		_next_chunk += 12;
323 		if (tmp >= 0xe0) {
324 			_channels[3].freq = tmp & 0xf;
325 			_value_ptr = &_channels[3].volume;
326 		} else {
327 			assert(!(tmp & 0x10));
328 			tmp = (tmp & 0x60) >> 5;
329 			_value_ptr = &_channels[tmp].freq;
330 			_channels[tmp].volume = 0;
331 		}
332 		*_value_ptr = _start;
333 		if (_channels[0].cmd_ptr) {
334 			tmp = READ_LE_UINT16(_channels[0].cmd_ptr);
335 			_start_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 2);
336 			_delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 4);
337 			_time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 6);
338 			_channels[0].cmd_ptr += 8;
339 			if (_value_ptr == &_channels[3].volume) {
340 				tmp = (tmp & 0x70) >> 4;
341 				if (tmp & 1)
342 					_value_ptr_2 = &_channels[tmp >> 1].volume;
343 				else
344 					_value_ptr_2 = &_channels[tmp >> 1].freq;
345 			} else {
346 				assert(!(tmp & 0x10));
347 				tmp = (tmp & 0x60) >> 5;
348 				_value_ptr_2 = &_channels[tmp].freq;
349 				_channels[tmp].volume = 0;
350 			}
351 			*_value_ptr_2 = _start_2;
352 		}
353 		debug(6, "chunk 1: %lu: %d step %d for %d, %lu: %d step %d for %d",
354 			  (long)(_value_ptr - (uint *)_channels), _start, _delta, _time_left,
355 			  (long)(_value_ptr_2 - (uint *)_channels), _start_2, _delta_2, _time_left_2);
356 		break;
357 
358 	case 2:
359 		_start = READ_LE_UINT16(_next_chunk);
360 		_end   = READ_LE_UINT16(_next_chunk + 2);
361 		_delta = (int16) READ_LE_UINT16(_next_chunk + 4);
362 		_channels[0].freq = 0;
363 		_next_chunk += 6;
364 		_forced_level = -1;
365 		debug(6, "chunk 2: %d -> %d step %d",
366 			  _start, _end, _delta);
367 		break;
368 	case 3:
369 		set_mplex(READ_LE_UINT16(_next_chunk));
370 		tmp = READ_LE_UINT16(_next_chunk + 2);
371 		assert((tmp & 0xf0) == 0xe0);
372 		_channels[3].freq = tmp & 0xf;
373 		if ((tmp & 3) == 3) {
374 			_next_chunk += 2;
375 			_channels[2].freq = READ_LE_UINT16(_next_chunk + 2);
376 		}
377 		_channels[3].volume = READ_LE_UINT16(_next_chunk + 4);
378 		_repeat_ctr = READ_LE_UINT16(_next_chunk + 6);
379 		_delta = (int16) READ_LE_UINT16(_next_chunk + 8);
380 		_next_chunk += 10;
381 		break;
382 	}
383 }
384 
nextPCjrCmd()385 void Player_V1::nextPCjrCmd() {
386 	uint i;
387 	int dummy;
388 	switch (_chunk_type) {
389 	case 0:
390 		for (i = 0; i < 4; i++) {
391 			if (!_channels[i].cmd_ptr)
392 				continue;
393 			if (!--_channels[i].notelen) {
394 				dummy = READ_LE_UINT16(_channels[i].cmd_ptr);
395 				if (dummy >= 0xfffe) {
396 					if (dummy == 0xfffe)
397 						_next_chunk = _current_data + 2;
398 					parsePCjrChunk();
399 					return;
400 				}
401 				_channels[i].notelen = 4 * dummy;
402 				dummy = READ_LE_UINT16(_channels[i].cmd_ptr + 2);
403 				if (dummy == 0) {
404 					_channels[i].hull_counter = 4;
405 					_channels[i].sustctr = _channels[i].sustain_2;
406 				} else {
407 					_channels[i].hull_counter = 1;
408 					_channels[i].freq = dummy;
409 				}
410 				debug(7, "chunk 0: channel %d play %d for %d",
411 					  i, dummy, _channels[i].notelen);
412 				_channels[i].cmd_ptr += 4;
413 			}
414 
415 
416 			switch (_channels[i].hull_counter) {
417 			case 1:
418 				_channels[i].volume -= _channels[i].attack;
419 				if ((int)_channels[i].volume <= 0) {
420 					_channels[i].volume = 0;
421 					_channels[i].hull_counter++;
422 				}
423 				break;
424 			case 2:
425 				_channels[i].volume += _channels[i].decay;
426 				if (_channels[i].volume >= _channels[i].level) {
427 					_channels[i].volume = _channels[i].level;
428 					_channels[i].hull_counter++;
429 				}
430 				break;
431 			case 4:
432 				if (--_channels[i].sustctr < 0) {
433 					_channels[i].sustctr = _channels[i].sustain_2;
434 					_channels[i].volume += _channels[i].sustain_1;
435 					if ((int)_channels[i].volume >= 15) {
436 						_channels[i].volume = 15;
437 						_channels[i].hull_counter++;
438 					}
439 				}
440 				break;
441 			}
442 		}
443 		break;
444 
445 	case 1:
446 		_start += _delta;
447 		*_value_ptr = _start;
448 		if (!--_time_left) {
449 			_start = READ_LE_UINT16(_next_chunk);
450 			_next_chunk += 2;
451 			if (_start == 0xffff) {
452 				parsePCjrChunk();
453 				return;
454 			}
455 			_delta = (int16) READ_LE_UINT16(_next_chunk);
456 			_time_left = READ_LE_UINT16(_next_chunk + 2);
457 			_next_chunk += 4;
458 			*_value_ptr = _start;
459 		}
460 
461 		if (_channels[0].cmd_ptr) {
462 			_start_2 += _delta_2;
463 			*_value_ptr_2 = _start_2;
464 			if (!--_time_left_2) {
465 				_start_2 = READ_LE_UINT16(_channels[0].cmd_ptr);
466 				if (_start_2 == 0xffff) {
467 					_next_chunk = _channels[0].cmd_ptr + 2;
468 					parsePCjrChunk();
469 					return;
470 				}
471 				_delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 2);
472 				_time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 4);
473 				_channels[0].cmd_ptr += 6;
474 			}
475 		}
476 		break;
477 
478 	case 2:
479 		_start += _delta;
480 		if (_start == _end) {
481 			parsePCjrChunk();
482 			return;
483 		}
484 		set_mplex(_start);
485 		debug(7, "chunk 2: mplex %d  curve %d", _start, _forced_level);
486 		_forced_level = -_forced_level;
487 		break;
488 	case 3:
489 		dummy = _channels[3].volume + _delta;
490 		if (dummy >= 15) {
491 			_channels[3].volume = 15;
492 		} else if (dummy <= 0) {
493 			_channels[3].volume = 0;
494 		} else {
495 			_channels[3].volume = dummy;
496 			break;
497 		}
498 
499 		if (!--_repeat_ctr) {
500 			parsePCjrChunk();
501 			return;
502 		}
503 		_delta = READ_LE_UINT16(_next_chunk);
504 		_next_chunk += 2;
505 		break;
506 	}
507 }
508 
set_mplex(uint mplex)509 void Player_V1::set_mplex(uint mplex) {
510 	if (mplex == 0)
511 		mplex = 65536;
512 	_mplex = mplex;
513 	_tick_len = _mplex_step * mplex;
514 }
515 
nextTick()516 void Player_V1::nextTick() {
517 	if (_next_chunk) {
518 		if (_pcjr)
519 			nextPCjrCmd();
520 		else
521 			nextSpeakerCmd();
522 	}
523 }
524 
generateSpkSamples(int16 * data,uint len)525 void Player_V1::generateSpkSamples(int16 *data, uint len) {
526 	uint i;
527 
528 	memset(data, 0, 2 * sizeof(int16) * len);
529 	if (_channels[0].freq == 0) {
530 		if (_forced_level) {
531 			int sample = _forced_level * _volumetable[0];
532 			for (i = 0; i < len; i++)
533 				data[2*i] = data[2*i+1] = sample;
534 			debug(9, "speaker: %8x: forced one", _tick_len);
535 		} else if (!_level) {
536 			return;
537 		}
538 	} else {
539 		squareGenerator(0, _channels[0].freq, 0, 0, data, len);
540 		debug(9, "speaker: %8x: freq %d %.1f", _tick_len,
541 				_channels[0].freq, 1193000.0 / _channels[0].freq);
542 	}
543 	lowPassFilter(data, len);
544 }
545 
generatePCjrSamples(int16 * data,uint len)546 void Player_V1::generatePCjrSamples(int16 *data, uint len) {
547 	uint i, j;
548 	uint freq, vol;
549 	bool hasdata = false;
550 
551 	memset(data, 0, 2 * sizeof(int16) * len);
552 
553 	if (_forced_level) {
554 		int sample = _forced_level * _volumetable[0];
555 		for (i = 0; i < len; i++)
556 			data[2*i] = data[2*i+1] = sample;
557 		hasdata = true;
558 		debug(9, "channel[4]: %8x: forced one", _tick_len);
559 	}
560 
561 	for (i = 1; i < 3; i++) {
562 		freq = _channels[i].freq;
563 		if (freq) {
564 			for (j = 0; j < i; j++) {
565 				if (freq == _channels[j].freq) {
566 					/* HACK: this channel is playing at
567 					 * the same frequency as another.
568 					 * Synchronize it to the same phase to
569 					 * prevent interference.
570 					 */
571 					_timer_count[i] = _timer_count[j];
572 					_timer_output ^= (1 << i) &
573 						(_timer_output ^ _timer_output << (i - j));
574 				}
575 			}
576 		}
577 	}
578 
579 	for (i = 0; i < 4; i++) {
580 		freq = _channels[i].freq;
581 		vol  = _channels[i].volume;
582 		if (!_volumetable[_channels[i].volume]) {
583 			_timer_count[i] -= len << FIXP_SHIFT;
584 			if (_timer_count[i] < 0)
585 				_timer_count[i] = 0;
586 		} else if (i < 3) {
587 			hasdata = true;
588 			squareGenerator(i, freq, vol, 0, data, len);
589 			debug(9, "channel[%d]: %8x: freq %d %.1f ; volume %d",
590 				  i, _tick_len, freq, 111860.0 / freq,  vol);
591 		} else {
592 			int noiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE;
593 			int n = (freq & 3);
594 
595 			freq = (n == 3) ? 2 * (_channels[2].freq) : 1 << (5 + n);
596 			hasdata = true;
597 			squareGenerator(i, freq, vol, noiseFB, data, len);
598 			debug(9, "channel[%d]: %x: noise freq %d %.1f ; volume %d",
599 				  i, _tick_len, freq, 111860.0 / freq,  vol);
600 		}
601 	}
602 
603 	if (_level || hasdata)
604 		lowPassFilter(data, len);
605 }
606 
607 } // End of namespace Scumm
608