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 "scumm/players/player_v2cms.h"
24 #include "scumm/scumm.h"
25 #include "audio/mixer.h"
26 #include "audio/softsynth/cms.h"
27 
28 namespace Scumm {
29 
Player_V2CMS(ScummEngine * scumm,Audio::Mixer * mixer)30 Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer)
31 	: Player_V2Base(scumm, mixer, true), _cmsVoicesBase(), _cmsVoices(),
32 	  _cmsChips(), _midiDelay(0), _octaveMask(0), _looping(0), _tempo(0),
33 	  _tempoSum(0), _midiData(0), _midiSongBegin(0), _musicTimer(0),
34 	  _musicTimerTicks(0), _voiceTimer(0), _loadedMidiSong(0),
35 	  _outputTableReady(0), _midiChannel(), _midiChannelUse(),
36 	  _lastMidiCommand(0) {
37 	setMusicVolume(255);
38 
39 	memset(_sfxFreq, 0xFF, sizeof(_sfxFreq));
40 	memset(_sfxAmpl, 0x00, sizeof(_sfxAmpl));
41 	memset(_sfxOctave, 0x66, sizeof(_sfxOctave));
42 
43 	_cmsVoices[0].amplitudeOutput = &_cmsChips[0].ampl[0];
44 	_cmsVoices[0].freqOutput = &_cmsChips[0].freq[0];
45 	_cmsVoices[0].octaveOutput = &_cmsChips[0].octave[0];
46 	_cmsVoices[1].amplitudeOutput = &_cmsChips[0].ampl[1];
47 	_cmsVoices[1].freqOutput = &_cmsChips[0].freq[1];
48 	_cmsVoices[1].octaveOutput = &_cmsChips[0].octave[0];
49 	_cmsVoices[2].amplitudeOutput = &_cmsChips[0].ampl[2];
50 	_cmsVoices[2].freqOutput = &_cmsChips[0].freq[2];
51 	_cmsVoices[2].octaveOutput = &_cmsChips[0].octave[1];
52 	_cmsVoices[3].amplitudeOutput = &_cmsChips[0].ampl[3];
53 	_cmsVoices[3].freqOutput = &_cmsChips[0].freq[3];
54 	_cmsVoices[3].octaveOutput = &_cmsChips[0].octave[1];
55 	_cmsVoices[4].amplitudeOutput = &_cmsChips[1].ampl[0];
56 	_cmsVoices[4].freqOutput = &_cmsChips[1].freq[0];
57 	_cmsVoices[4].octaveOutput = &_cmsChips[1].octave[0];
58 	_cmsVoices[5].amplitudeOutput = &_cmsChips[1].ampl[1];
59 	_cmsVoices[5].freqOutput = &_cmsChips[1].freq[1];
60 	_cmsVoices[5].octaveOutput = &_cmsChips[1].octave[0];
61 	_cmsVoices[6].amplitudeOutput = &_cmsChips[1].ampl[2];
62 	_cmsVoices[6].freqOutput = &_cmsChips[1].freq[2];
63 	_cmsVoices[6].octaveOutput = &_cmsChips[1].octave[1];
64 	_cmsVoices[7].amplitudeOutput = &_cmsChips[1].ampl[3];
65 	_cmsVoices[7].freqOutput = &_cmsChips[1].freq[3];
66 	_cmsVoices[7].octaveOutput = &_cmsChips[1].octave[1];
67 
68 	// inits the CMS Emulator like in the original
69 	_cmsEmu = new CMSEmulator(_sampleRate);
70 	for (int i = 0, cmsPort = 0x220; i < 2; cmsPort += 2, ++i) {
71 		for (int off = 0; off < 13; ++off) {
72 			_cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
73 			_cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
74 		}
75 	}
76 
77 	_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
78 }
79 
~Player_V2CMS()80 Player_V2CMS::~Player_V2CMS() {
81 	Common::StackLock lock(_mutex);
82 
83 	_mixer->stopHandle(_soundHandle);
84 	delete _cmsEmu;
85 }
86 
setMusicVolume(int vol)87 void Player_V2CMS::setMusicVolume(int vol) {
88 }
89 
getMusicTimer()90 int Player_V2CMS::getMusicTimer() {
91 	return _midiData ? _musicTimer : Player_V2Base::getMusicTimer();
92 }
93 
stopAllSounds()94 void Player_V2CMS::stopAllSounds() {
95 	Common::StackLock lock(_mutex);
96 
97 	for (int i = 0; i < 4; i++) {
98 		clear_channel(i);
99 	}
100 	_next_nr = _current_nr = 0;
101 	_next_data = _current_data = 0;
102 	_midiData = 0;
103 	_midiSongBegin = 0;
104 	_midiDelay = 0;
105 	_musicTimer = _musicTimerTicks = 0;
106 	offAllChannels();
107 }
108 
stopSound(int nr)109 void Player_V2CMS::stopSound(int nr) {
110 	Common::StackLock lock(_mutex);
111 
112 	if (_next_nr == nr) {
113 		_next_nr = 0;
114 		_next_data = 0;
115 	}
116 	if (_current_nr == nr) {
117 		for (int i = 0; i < 4; i++) {
118 			clear_channel(i);
119 		}
120 		_current_nr = 0;
121 		_current_data = 0;
122 		chainNextSound();
123 	}
124 	if (_loadedMidiSong == nr) {
125 		_midiData = 0;
126 		_midiSongBegin = 0;
127 		_midiDelay = 0;
128 		offAllChannels();
129 	}
130 }
131 
startSound(int nr)132 void Player_V2CMS::startSound(int nr) {
133 	Common::StackLock lock(_mutex);
134 
135 	byte *data = _vm->getResourceAddress(rtSound, nr);
136 	assert(data);
137 
138 	if (data[6] == 0x80) {
139 		_musicTimer = _musicTimerTicks = 0;
140 		loadMidiData(data, nr);
141 	} else {
142 		int cprio = _current_data ? *(_current_data + _header_len) : 0;
143 		int prio  = *(data + _header_len);
144 		int nprio = _next_data ? *(_next_data + _header_len) : 0;
145 
146 		int restartable = *(data + _header_len + 1);
147 
148 		if (!_current_nr || cprio <= prio) {
149 			int tnr = _current_nr;
150 			int tprio = cprio;
151 			byte *tdata  = _current_data;
152 
153 			chainSound(nr, data);
154 			nr   = tnr;
155 			prio = tprio;
156 			data = tdata;
157 			restartable = data ? *(data + _header_len + 1) : 0;
158 		}
159 
160 		if (!_current_nr) {
161 			nr = 0;
162 			_next_nr = 0;
163 			_next_data = 0;
164 		}
165 
166 		if (nr != _current_nr
167 			&& restartable
168 			&& (!_next_nr
169 			|| nprio <= prio)) {
170 
171 			_next_nr = nr;
172 			_next_data = data;
173 		}
174 	}
175 }
176 
loadMidiData(byte * data,int sound)177 void Player_V2CMS::loadMidiData(byte *data, int sound) {
178 	memset(_midiChannelUse, 0, sizeof(_midiChannelUse));
179 	memset(_midiChannel, 0, sizeof(_midiChannel));
180 
181 	_tempo = data[7];
182 	_looping = data[8];
183 
184 	byte channels = data[14];
185 	byte curChannel = 0;
186 	byte *voice2 = data + 23;
187 
188 	for (; channels != 0; ++curChannel, --channels, voice2 += 16) {
189 		if (*(data + 15 + curChannel)) {
190 			byte channel = *(data + 15 + curChannel) - 1;
191 			_midiChannelUse[channel] = 1;
192 
193 			Voice *voiceDef = &_cmsVoicesBase[channel];
194 
195 			byte attackDecay = voice2[10];
196 			voiceDef->attack = _attackRate[attackDecay >> 4];
197 			voiceDef->decay = _decayRate[attackDecay & 0x0F];
198 			byte sustainRelease = voice2[11];
199 			voiceDef->sustain = _sustainRate[sustainRelease >> 4];
200 			voiceDef->release = _releaseRate[sustainRelease & 0x0F];
201 
202 			if (voice2[3] & 0x40) {
203 				voiceDef->vibrato = 0x0301;
204 				if (voice2[13] & 0x40) {
205 					voiceDef->vibrato = 0x0601;
206 				}
207 			} else {
208 				voiceDef->vibrato = 0;
209 			}
210 
211 			if (voice2[8] & 0x80) {
212 				voiceDef->vibrato2 = 0x0506;
213 				if (voice2[13] & 0x80) {
214 					voiceDef->vibrato2 = 0x050C;
215 				}
216 			} else {
217 				voiceDef->vibrato2 = 0;
218 			}
219 
220 			if ((voice2[8] & 0x0F) > 1) {
221 				voiceDef->octadd = 0x01;
222 			} else {
223 				voiceDef->octadd = 0x00;
224 			}
225 		}
226 	}
227 
228 	for (int i = 0; i < 8; ++i) {
229 		_cmsVoices[i].chanNumber = 0xFF;
230 		_cmsVoices[i].curVolume = 0;
231 		_cmsVoices[i].nextVoice = 0;
232 	}
233 
234 	_midiDelay = 0;
235 	memset(_cmsChips, 0, sizeof(MusicChip)*2);
236 	_midiData = data + 151;
237 	_midiSongBegin = _midiData + data[9];
238 
239 	_loadedMidiSong = sound;
240 }
241 
getSoundStatus(int nr) const242 int Player_V2CMS::getSoundStatus(int nr) const {
243 	return _current_nr == nr || _next_nr == nr || _loadedMidiSong == nr;
244 }
245 
processMidiData()246 void Player_V2CMS::processMidiData() {
247 	byte *currentData = _midiData;
248 	byte command = 0x00;
249 	int16 temp = 0;
250 
251 	++_musicTimerTicks;
252 	if (_musicTimerTicks > 60) {
253 		_musicTimerTicks = 0;
254 		++_musicTimer;
255 	}
256 
257 	if (!_midiDelay) {
258 		while (true) {
259 			if ((command = *currentData++) == 0xFF) {
260 				if ((command = *currentData++) == 0x2F) {
261 					if (_looping == 0) {
262 						currentData = _midiData = _midiSongBegin;
263 						continue;
264 					}
265 					_midiData = _midiSongBegin = 0;
266 					_midiDelay = 0;
267 					_loadedMidiSong = 0;
268 					offAllChannels();
269 					return;
270 				} else {
271 					if (command == 0x58) {
272 						currentData += 6;
273 					}
274 				}
275 			} else {
276 				_lastMidiCommand = command;
277 				if (command < 0x90) {
278 					clearNote(currentData);
279 				} else {
280 					playNote(currentData);
281 				}
282 			}
283 
284 			temp = command = *currentData++;
285 			if (command & 0x80) {
286 				temp = (command & 0x7F) << 8;
287 				command = *currentData++;
288 				temp |= (command << 1);
289 				temp >>= 1;
290 			}
291 			temp >>= 1;
292 			int lastBit = temp & 1;
293 			temp >>= 1;
294 			temp += lastBit;
295 
296 			if (temp)
297 				break;
298 		}
299 		_midiData = currentData;
300 		_midiDelay = temp;
301 	}
302 
303 	--_midiDelay;
304 	if (_midiDelay < 0)
305 		_midiDelay = 0;
306 
307 	return;
308 }
309 
readBuffer(int16 * buffer,const int numSamples)310 int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) {
311 	Common::StackLock lock(_mutex);
312 
313 	uint step = 1;
314 	int len = numSamples / 2;
315 
316 	// maybe this needs a complete rewrite
317 	do {
318 		if (!(_next_tick >> FIXP_SHIFT)) {
319 			if (_midiData) {
320 				--_voiceTimer;
321 				if (!(_voiceTimer & 0x01))
322 					playVoice();
323 
324 				int newTempoSum = _tempo + _tempoSum;
325 				_tempoSum = newTempoSum & 0xFF;
326 				if (newTempoSum > 0xFF)
327 					processMidiData();
328 			} else {
329 				nextTick();
330 				play();
331 			}
332 			_next_tick += _tick_len;
333 		}
334 
335 		step = len;
336 		if (step > (_next_tick >> FIXP_SHIFT))
337 			step = (_next_tick >> FIXP_SHIFT);
338 		_cmsEmu->readBuffer(buffer, step);
339 		buffer += 2 * step;
340 		_next_tick -= step << FIXP_SHIFT;
341 	} while (len -= step);
342 
343 	return numSamples;
344 }
345 
playVoice()346 void Player_V2CMS::playVoice() {
347 	if (_outputTableReady) {
348 		playMusicChips(_cmsChips);
349 		_outputTableReady = 0;
350 	}
351 
352 	_octaveMask = 0xF0;
353 	Voice2 *voice = 0;
354 	for (int i = 0; i < 8; ++i) {
355 		voice = &_cmsVoices[i];
356 		_octaveMask = ~_octaveMask;
357 
358 		if (voice->chanNumber != 0xFF) {
359 			processChannel(voice);
360 		} else {
361 			if (!voice->curVolume) {
362 				*(voice->amplitudeOutput) = 0;
363 			}
364 
365 			int volume = voice->curVolume - voice->releaseRate;
366 			if (volume < 0)
367 				volume = 0;
368 
369 			voice->curVolume = volume;
370 			*(voice->amplitudeOutput) = ((volume >> 4) | (volume & 0xF0)) & voice->channel;
371 			++_outputTableReady;
372 		}
373 	}
374 }
375 
processChannel(Voice2 * channel)376 void Player_V2CMS::processChannel(Voice2 *channel) {
377 	++_outputTableReady;
378 	switch (channel->nextProcessState) {
379 	case Voice2::kEnvelopeAttack:
380 		processAttack(channel);
381 		break;
382 
383 	case Voice2::kEnvelopeDecay:
384 		processDecay(channel);
385 		break;
386 
387 	case Voice2::kEnvelopeSustain:
388 		processSustain(channel);
389 		break;
390 
391 	case Voice2::kEnvelopeRelease:
392 		processRelease(channel);
393 		break;
394 	}
395 }
396 
processRelease(Voice2 * channel)397 void Player_V2CMS::processRelease(Voice2 *channel) {
398 	int newVolume = channel->curVolume - channel->releaseRate;
399 	if (newVolume < 0)
400 		newVolume = 0;
401 
402 	channel->curVolume = newVolume;
403 	processVibrato(channel);
404 }
405 
processAttack(Voice2 * channel)406 void Player_V2CMS::processAttack(Voice2 *channel) {
407 	int newVolume = channel->curVolume + channel->attackRate;
408 	if (newVolume > channel->maxAmpl) {
409 		channel->curVolume = channel->maxAmpl;
410 		channel->nextProcessState = Voice2::kEnvelopeDecay;
411 	} else {
412 		channel->curVolume = newVolume;
413 	}
414 
415 	processVibrato(channel);
416 }
417 
processDecay(Voice2 * channel)418 void Player_V2CMS::processDecay(Voice2 *channel) {
419 	int newVolume = channel->curVolume - channel->decayRate;
420 	if (newVolume <= channel->sustainRate) {
421 		channel->curVolume = channel->sustainRate;
422 		channel->nextProcessState = Voice2::kEnvelopeSustain;
423 	} else {
424 		channel->curVolume = newVolume;
425 	}
426 
427 	processVibrato(channel);
428 }
429 
processSustain(Voice2 * channel)430 void Player_V2CMS::processSustain(Voice2 *channel) {
431 	if (channel->unkVibratoRate) {
432 		int16 volume = channel->curVolume + channel->unkRate;
433 		if (volume & 0xFF00) {
434 			volume = int8(volume >> 8);
435 			volume = -volume;
436 		}
437 
438 		channel->curVolume = volume;
439 		--channel->unkCount;
440 		if (!channel->unkCount) {
441 			channel->unkRate = -channel->unkRate;
442 			channel->unkCount = (channel->unkVibratoDepth & 0x0F) << 1;
443 		}
444 	}
445 	processVibrato(channel);
446 }
447 
processVibrato(Voice2 * channel)448 void Player_V2CMS::processVibrato(Voice2 *channel) {
449 	if (channel->vibratoRate) {
450 		int16 temp = channel->curFreq + channel->curVibratoRate;
451 		channel->curOctave += (temp & 0xFF00) >> 8;
452 		channel->curFreq = temp & 0xFF;
453 
454 		--channel->curVibratoUnk;
455 		if (!channel->curVibratoUnk) {
456 			channel->curVibratoRate = -channel->curVibratoRate;
457 			channel->curVibratoUnk = (channel->vibratoDepth & 0x0F) << 1;
458 		}
459 	}
460 
461 	byte *output = channel->amplitudeOutput;
462 	*output = ((channel->curVolume >> 4) | (channel->curVolume & 0xF0)) & channel->channel;
463 	output = channel->freqOutput;
464 	*output = channel->curFreq;
465 	output = channel->octaveOutput;
466 	*output = (((channel->curOctave << 4) | (channel->curOctave & 0x0F)) & _octaveMask) | ((~_octaveMask) & *output);
467 }
468 
offAllChannels()469 void Player_V2CMS::offAllChannels() {
470 	for (int cmsPort = 0x220, i = 0; i < 2; cmsPort += 2, ++i) {
471 		for (int off = 1; off <= 10; ++off) {
472 			_cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
473 			_cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
474 		}
475 	}
476 }
477 
getFreeVoice()478 Player_V2CMS::Voice2 *Player_V2CMS::getFreeVoice() {
479 	Voice2 *curVoice = 0;
480 	Voice2 *selected = 0;
481 	uint8 volume = 0xFF;
482 
483 	for (int i = 0; i < 8; ++i) {
484 		curVoice = &_cmsVoices[i];
485 
486 		if (curVoice->chanNumber == 0xFF) {
487 			if (!curVoice->curVolume) {
488 				selected = curVoice;
489 				break;
490 			}
491 
492 			if (curVoice->curVolume < volume) {
493 				selected = curVoice;
494 				volume = selected->curVolume;
495 			}
496 		}
497 	}
498 
499 	if (selected) {
500 		selected->chanNumber = _lastMidiCommand & 0x0F;
501 
502 		uint8 channel = selected->chanNumber;
503 		Voice2 *oldChannel = _midiChannel[channel];
504 		_midiChannel[channel] = selected;
505 		selected->nextVoice = oldChannel;
506 	}
507 
508 	return selected;
509 }
510 
playNote(byte * & data)511 void Player_V2CMS::playNote(byte *&data) {
512 	byte channel = _lastMidiCommand & 0x0F;
513 	if (_midiChannelUse[channel]) {
514 		Voice2 *freeVoice = getFreeVoice();
515 		if (freeVoice) {
516 			Voice *voice = &_cmsVoicesBase[freeVoice->chanNumber];
517 			freeVoice->attackRate = voice->attack;
518 			freeVoice->decayRate = voice->decay;
519 			freeVoice->sustainRate = voice->sustain;
520 			freeVoice->releaseRate = voice->release;
521 			freeVoice->octaveAdd = voice->octadd;
522 			freeVoice->vibratoRate = freeVoice->curVibratoRate = voice->vibrato & 0xFF;
523 			freeVoice->vibratoDepth = freeVoice->curVibratoUnk = voice->vibrato >> 8;
524 			freeVoice->unkVibratoRate = freeVoice->unkRate = voice->vibrato2 & 0xFF;
525 			freeVoice->unkVibratoDepth = freeVoice->unkCount = voice->vibrato2 >> 8;
526 			freeVoice->maxAmpl = 0xFF;
527 
528 			uint8 rate = freeVoice->attackRate;
529 			uint8 volume = freeVoice->curVolume >> 1;
530 
531 			if (rate < volume)
532 				rate = volume;
533 
534 			rate -= freeVoice->attackRate;
535 			freeVoice->curVolume = rate;
536 			freeVoice->playingNote = *data;
537 
538 			int effectiveNote = freeVoice->playingNote + 3;
539 			if (effectiveNote < 0 || effectiveNote >= ARRAYSIZE(_midiNotes)) {
540 				warning("Player_V2CMS::playNote: Note %d out of bounds", effectiveNote);
541 				effectiveNote = CLIP<int>(effectiveNote, 0, ARRAYSIZE(_midiNotes) - 1);
542 			}
543 
544 			int octave = _midiNotes[effectiveNote].baseOctave + freeVoice->octaveAdd - 3;
545 			if (octave < 0)
546 				octave = 0;
547 			if (octave > 7)
548 				octave = 7;
549 			if (!octave)
550 				++octave;
551 			freeVoice->curOctave = octave;
552 			freeVoice->curFreq = _midiNotes[effectiveNote].frequency;
553 			freeVoice->curVolume = 0;
554 			freeVoice->nextProcessState = Voice2::kEnvelopeAttack;
555 			if (!(_lastMidiCommand & 1))
556 				freeVoice->channel = 0xF0;
557 			else
558 				freeVoice->channel = 0x0F;
559 		}
560 	}
561 	data += 2;
562 }
563 
getPlayVoice(byte param)564 Player_V2CMS::Voice2 *Player_V2CMS::getPlayVoice(byte param) {
565 	byte channelNum = _lastMidiCommand & 0x0F;
566 	Voice2 *curVoice = _midiChannel[channelNum];
567 
568 	if (curVoice) {
569 		Voice2 *prevVoice = 0;
570 		while (true) {
571 			if (curVoice->playingNote == param)
572 				break;
573 
574 			prevVoice = curVoice;
575 			curVoice = curVoice->nextVoice;
576 			if (!curVoice)
577 				return 0;
578 		}
579 
580 		if (prevVoice)
581 			prevVoice->nextVoice = curVoice->nextVoice;
582 		else
583 			_midiChannel[channelNum] = curVoice->nextVoice;
584 	}
585 
586 	return curVoice;
587 }
588 
clearNote(byte * & data)589 void Player_V2CMS::clearNote(byte *&data) {
590 	Voice2 *voice = getPlayVoice(*data);
591 	if (voice) {
592 		voice->chanNumber = 0xFF;
593 		voice->nextVoice = 0;
594 		voice->nextProcessState = Voice2::kEnvelopeRelease;
595 	}
596 	data += 2;
597 }
598 
play()599 void Player_V2CMS::play() {
600 	_octaveMask = 0xF0;
601 	channel_data *chan = &_channels[0].d;
602 
603 	byte noiseGen = 3;
604 
605 	for (int i = 1; i <= 4; ++i) {
606 		if (chan->time_left) {
607 			uint16 freq = chan->freq;
608 
609 			if (i == 4) {
610 				if ((freq >> 8) & 0x40) {
611 					noiseGen = freq & 0xFF;
612 				} else {
613 					noiseGen = 3;
614 					_sfxFreq[0] = _sfxFreq[3];
615 					_sfxOctave[0] = (_sfxOctave[0] & 0xF0) | ((_sfxOctave[1] & 0xF0) >> 4);
616 				}
617 			} else {
618 				if (freq == 0) {
619 					freq = 0xFFC0;
620 				}
621 
622 				int cmsOct = 2;
623 				int freqOct = 0x8000;
624 
625 				while (true) {
626 					if (freq >= freqOct) {
627 						break;
628 					}
629 					freqOct >>= 1;
630 					++cmsOct;
631 					if (cmsOct == 8) {
632 						--cmsOct;
633 						freq = 1024;
634 						break;
635 					}
636 				}
637 				byte oct = cmsOct << 4;
638 				oct |= cmsOct;
639 
640 				oct &= _octaveMask;
641 				oct |= (~_octaveMask) & _sfxOctave[(i & 3) >> 1];
642 				_sfxOctave[(i & 3) >> 1] = oct;
643 
644 				freq >>= -(cmsOct - 9);
645 				_sfxFreq[i & 3] = (-(freq - 511)) & 0xFF;
646 			}
647 			_sfxAmpl[i & 3] = _volumeTable[chan->volume >> 12];
648 		} else {
649 			_sfxAmpl[i & 3] = 0;
650 		}
651 
652 		chan = &_channels[i].d;
653 		_octaveMask ^= 0xFF;
654 	}
655 
656 	// with the high nibble of the volumeReg value
657 	// the right channels amplitude is set
658 	// with the low value the left channels amplitude
659 	_cmsEmu->portWrite(0x221, 0);
660 	_cmsEmu->portWrite(0x220, _sfxAmpl[0]);
661 	_cmsEmu->portWrite(0x221, 1);
662 	_cmsEmu->portWrite(0x220, _sfxAmpl[1]);
663 	_cmsEmu->portWrite(0x221, 2);
664 	_cmsEmu->portWrite(0x220, _sfxAmpl[2]);
665 	_cmsEmu->portWrite(0x221, 3);
666 	_cmsEmu->portWrite(0x220, _sfxAmpl[3]);
667 	_cmsEmu->portWrite(0x221, 8);
668 	_cmsEmu->portWrite(0x220, _sfxFreq[0]);
669 	_cmsEmu->portWrite(0x221, 9);
670 	_cmsEmu->portWrite(0x220, _sfxFreq[1]);
671 	_cmsEmu->portWrite(0x221, 10);
672 	_cmsEmu->portWrite(0x220, _sfxFreq[2]);
673 	_cmsEmu->portWrite(0x221, 11);
674 	_cmsEmu->portWrite(0x220, _sfxFreq[3]);
675 	_cmsEmu->portWrite(0x221, 0x10);
676 	_cmsEmu->portWrite(0x220, _sfxOctave[0]);
677 	_cmsEmu->portWrite(0x221, 0x11);
678 	_cmsEmu->portWrite(0x220, _sfxOctave[1]);
679 	_cmsEmu->portWrite(0x221, 0x14);
680 	_cmsEmu->portWrite(0x220, 0x3E);
681 	_cmsEmu->portWrite(0x221, 0x15);
682 	_cmsEmu->portWrite(0x220, 0x01);
683 	_cmsEmu->portWrite(0x221, 0x16);
684 	_cmsEmu->portWrite(0x220, noiseGen);
685 }
686 
playMusicChips(const MusicChip * table)687 void Player_V2CMS::playMusicChips(const MusicChip *table) {
688 	int cmsPort = 0x21E;
689 
690 	do {
691 		cmsPort += 2;
692 		_cmsEmu->portWrite(cmsPort+1, 0);
693 		_cmsEmu->portWrite(cmsPort, table->ampl[0]);
694 		_cmsEmu->portWrite(cmsPort+1, 1);
695 		_cmsEmu->portWrite(cmsPort, table->ampl[1]);
696 		_cmsEmu->portWrite(cmsPort+1, 2);
697 		_cmsEmu->portWrite(cmsPort, table->ampl[2]);
698 		_cmsEmu->portWrite(cmsPort+1, 3);
699 		_cmsEmu->portWrite(cmsPort, table->ampl[3]);
700 		_cmsEmu->portWrite(cmsPort+1, 8);
701 		_cmsEmu->portWrite(cmsPort, table->freq[0]);
702 		_cmsEmu->portWrite(cmsPort+1, 9);
703 		_cmsEmu->portWrite(cmsPort, table->freq[1]);
704 		_cmsEmu->portWrite(cmsPort+1, 10);
705 		_cmsEmu->portWrite(cmsPort, table->freq[2]);
706 		_cmsEmu->portWrite(cmsPort+1, 11);
707 		_cmsEmu->portWrite(cmsPort, table->freq[3]);
708 		_cmsEmu->portWrite(cmsPort+1, 0x10);
709 		_cmsEmu->portWrite(cmsPort, table->octave[0]);
710 		_cmsEmu->portWrite(cmsPort+1, 0x11);
711 		_cmsEmu->portWrite(cmsPort, table->octave[1]);
712 		_cmsEmu->portWrite(cmsPort+1, 0x14);
713 		_cmsEmu->portWrite(cmsPort, 0x3F);
714 		_cmsEmu->portWrite(cmsPort+1, 0x15);
715 		_cmsEmu->portWrite(cmsPort, 0x00);
716 		++table;
717 	} while ((cmsPort & 2) == 0);
718 }
719 
720 const Player_V2CMS::MidiNote Player_V2CMS::_midiNotes[132] = {
721 	{   3,  0 }, {  31,  0 }, {  58,  0 }, {  83,  0 },
722 	{ 107,  0 }, { 130,  0 }, { 151,  0 }, { 172,  0 },
723 	{ 191,  0 }, { 209,  0 }, { 226,  0 }, { 242,  0 },
724 	{   3,  1 }, {  31,  1 }, {  58,  1 }, {  83,  1 },
725 	{ 107,  1 }, { 130,  1 }, { 151,  1 }, { 172,  1 },
726 	{ 191,  1 }, { 209,  1 }, { 226,  1 }, { 242,  1 },
727 	{   3,  2 }, {  31,  2 }, {  58,  2 }, {  83,  2 },
728 	{ 107,  2 }, { 130,  2 }, { 151,  2 }, { 172,  2 },
729 	{ 191,  2 }, { 209,  2 }, { 226,  2 }, { 242,  2 },
730 	{   3,  3 }, {  31,  3 }, {  58,  3 }, {  83,  3 },
731 	{ 107,  3 }, { 130,  3 }, { 151,  3 }, { 172,  3 },
732 	{ 191,  3 }, { 209,  3 }, { 226,  3 }, { 242,  3 },
733 	{   3,  4 }, {  31,  4 }, {  58,  4 }, {  83,  4 },
734 	{ 107,  4 }, { 130,  4 }, { 151,  4 }, { 172,  4 },
735 	{ 191,  4 }, { 209,  4 }, { 226,  4 }, { 242,  4 },
736 	{   3,  5 }, {  31,  5 }, {  58,  5 }, {  83,  5 },
737 	{ 107,  5 }, { 130,  5 }, { 151,  5 }, { 172,  5 },
738 	{ 191,  5 }, { 209,  5 }, { 226,  5 }, { 242,  5 },
739 	{   3,  6 }, {  31,  6 }, {  58,  6 }, {  83,  6 },
740 	{ 107,  6 }, { 130,  6 }, { 151,  6 }, { 172,  6 },
741 	{ 191,  6 }, { 209,  6 }, { 226,  6 }, { 242,  6 },
742 	{   3,  7 }, {  31,  7 }, {  58,  7 }, {  83,  7 },
743 	{ 107,  7 }, { 130,  7 }, { 151,  7 }, { 172,  7 },
744 	{ 191,  7 }, { 209,  7 }, { 226,  7 }, { 242,  7 },
745 	{   3,  8 }, {  31,  8 }, {  58,  8 }, {  83,  8 },
746 	{ 107,  8 }, { 130,  8 }, { 151,  8 }, { 172,  8 },
747 	{ 191,  8 }, { 209,  8 }, { 226,  8 }, { 242,  8 },
748 	{   3,  9 }, {  31,  9 }, {  58,  9 }, {  83,  9 },
749 	{ 107,  9 }, { 130,  9 }, { 151,  9 }, { 172,  9 },
750 	{ 191,  9 }, { 209,  9 }, { 226,  9 }, { 242,  9 },
751 	{   3, 10 }, {  31, 10 }, {  58, 10 }, {  83, 10 },
752 	{ 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 },
753 	{ 191, 10 }, { 209, 10 }, { 226, 10 }, { 242, 10 }
754 };
755 
756 const byte Player_V2CMS::_attackRate[16] = {
757 	  0,   2,   4,   7,  14,  26,  48,  82,
758 	128, 144, 160, 176, 192, 208, 224, 255
759 };
760 
761 const byte Player_V2CMS::_decayRate[16] = {
762 	  0,   1,   2,   3,   4,   6,  12,  24,
763 	 48,  96, 192, 215, 255, 255, 255, 255
764 };
765 
766 const byte Player_V2CMS::_sustainRate[16] = {
767 	255, 180, 128,  96,  80,  64,  56,  48,
768 	 42,  36,  32,  28,  24,  20,  16,   0
769 };
770 
771 const byte Player_V2CMS::_releaseRate[16] = {
772 	  0,   1,   2,   4,   6,   9,  14,  22,
773 	 36,  56,  80, 100, 120, 140, 160, 255
774 };
775 
776 const byte Player_V2CMS::_volumeTable[16] = {
777 	0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22,
778 	0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF
779 };
780 
781 const byte Player_V2CMS::_cmsInitData[26] = {
782 	0x1C, 0x02,
783 	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
784 	0x14, 0x3F, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1C, 0x01
785 };
786 
787 } // End of namespace Scumm
788