diff options
Diffstat (limited to 'engines/scumm/player/v1.cpp')
-rw-r--r-- | engines/scumm/player/v1.cpp | 607 |
1 files changed, 0 insertions, 607 deletions
diff --git a/engines/scumm/player/v1.cpp b/engines/scumm/player/v1.cpp deleted file mode 100644 index 25f42f143c..0000000000 --- a/engines/scumm/player/v1.cpp +++ /dev/null @@ -1,607 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - - -#include "engines/engine.h" -#include "scumm/player/v1.h" -#include "scumm/scumm.h" - -namespace Scumm { - -#define FB_WNOISE 0x12000 /* feedback for white noise */ -#define FB_PNOISE 0x08000 /* feedback for periodic noise */ - -#define TIMER_BASE_FREQ 1193000 -#define FIXP_SHIFT 16 - -Player_V1::Player_V1(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr) - : Player_V2(scumm, mixer, pcjr) { - // Initialize channel code - for (int i = 0; i < 4; ++i) - clear_channel(i); - - _mplex_step = (_sampleRate << FIXP_SHIFT) / 1193000; - _next_chunk = _repeat_chunk = 0; - _forced_level = 0; - _random_lsr = 0; -} - -Player_V1::~Player_V1() { -} - -void Player_V1::chainSound(int nr, byte *data) { - uint i; - for (i = 0; i < 4; ++i) - clear_channel(i); - - _current_nr = nr; - _current_data = data; - _repeat_chunk = _next_chunk = data + (_pcjr ? 2 : 4); - - debug(4, "Chaining new sound %d", nr); - if (_pcjr) - parsePCjrChunk(); - else - parseSpeakerChunk(); -} - -void Player_V1::startSound(int nr) { - Common::StackLock lock(_mutex); - - byte *data = _vm->getResourceAddress(rtSound, nr); - assert(data); - - int offset = _pcjr ? READ_LE_UINT16(data+4) : 6; - int cprio = _current_data ? *(_current_data) & 0x7f : 0; - int prio = *(data + offset) & 0x7f; - int restartable = *(data + offset) & 0x80; - - debug(4, "startSound %d: prio %d%s, cprio %d", - nr, prio, restartable ? " restartable" : "", cprio); - - if (!_current_nr || cprio <= prio) { - if (_current_data && (*(_current_data) & 0x80)) { - _next_nr = _current_nr; - _next_data = _current_data; - } - - chainSound(nr, data + offset); - } -} - -void Player_V1::stopAllSounds() { - Common::StackLock lock(_mutex); - - for (int i = 0; i < 4; i++) - clear_channel(i); - _repeat_chunk = _next_chunk = 0; - _next_nr = _current_nr = 0; - _next_data = _current_data = 0; -} - -void Player_V1::stopSound(int nr) { - Common::StackLock lock(_mutex); - - if (_next_nr == nr) { - _next_nr = 0; - _next_data = 0; - } - if (_current_nr == nr) { - for (int i = 0; i < 4; i++) { - clear_channel(i); - } - _repeat_chunk = _next_chunk = 0; - _current_nr = 0; - _current_data = 0; - chainNextSound(); - } -} - -void Player_V1::clear_channel(int i) { - _channels[i].freq = 0; - _channels[i].volume = 15; -} - -int Player_V1::getMusicTimer() { - /* Do V1 games have a music timer? */ - return 0; -} - -void Player_V1::parseSpeakerChunk() { - set_mplex(3000); - _forced_level = 0; - - parse_again: - _chunk_type = READ_LE_UINT16(_next_chunk); - debug(6, "parseSpeakerChunk: sound %d, offset %lx, chunk %x", - _current_nr, (long)(_next_chunk - _current_data), _chunk_type); - - _next_chunk += 2; - switch (_chunk_type) { - case 0xffff: - _current_nr = 0; - _current_data = 0; - _channels[0].freq = 0; - _next_chunk = 0; - chainNextSound(); - break; - case 0xfffe: - _repeat_chunk = _next_chunk; - goto parse_again; - - case 0xfffd: - _next_chunk = _repeat_chunk; - goto parse_again; - - case 0xfffc: - /* handle reset. We don't need this do we? */ - goto parse_again; - - case 0: - _time_left = 1; - set_mplex(READ_LE_UINT16(_next_chunk)); - _next_chunk += 2; - break; - case 1: - set_mplex(READ_LE_UINT16(_next_chunk)); - _start = READ_LE_UINT16(_next_chunk + 2); - _end = READ_LE_UINT16(_next_chunk + 4); - _delta = (int16) READ_LE_UINT16(_next_chunk + 6); - _repeat_ctr = READ_LE_UINT16(_next_chunk + 8); - _channels[0].freq = _start; - _next_chunk += 10; - debug(6, "chunk 1: mplex %d, freq %d -> %d step %d x %d", - _mplex, _start, _end, _delta, _repeat_ctr); - break; - case 2: - _start = READ_LE_UINT16(_next_chunk); - _end = READ_LE_UINT16(_next_chunk + 2); - _delta = (int16) READ_LE_UINT16(_next_chunk + 4); - _channels[0].freq = 0; - _next_chunk += 6; - _forced_level = -1; - debug(6, "chunk 2: %d -> %d step %d", - _start, _end, _delta); - break; - case 3: - _start = READ_LE_UINT16(_next_chunk); - _end = READ_LE_UINT16(_next_chunk + 2); - _delta = (int16) READ_LE_UINT16(_next_chunk + 4); - _channels[0].freq = 0; - _next_chunk += 6; - _forced_level = -1; - debug(6, "chunk 3: %d -> %d step %d", - _start, _end, _delta); - break; - } -} - -void Player_V1::nextSpeakerCmd() { - uint16 lsr; - switch (_chunk_type) { - case 0: - if (--_time_left) - return; - _time_left = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - if (_time_left == 0xfffb) { - /* handle 0xfffb?? */ - _time_left = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - } - debug(7, "nextSpeakerCmd: chunk %d, offset %4lx: notelen %d", - _chunk_type, (long)(_next_chunk - 2 - _current_data), _time_left); - if (_time_left == 0) { - parseSpeakerChunk(); - } else { - _channels[0].freq = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - debug(7, "freq_current: %d", _channels[0].freq); - } - break; - - case 1: - _channels[0].freq = (_channels[0].freq + _delta) & 0xffff; - if (_channels[0].freq == _end) { - if (!--_repeat_ctr) { - parseSpeakerChunk(); - return; - } - _channels[0].freq = _start; - } - break; - - case 2: - _start = (_start + _delta) & 0xffff; - if (_start == _end) { - parseSpeakerChunk(); - return; - } - set_mplex(_start); - _forced_level = -_forced_level; - break; - case 3: - _start = (_start + _delta) & 0xffff; - if (_start == _end) { - parseSpeakerChunk(); - return; - } - lsr = _random_lsr + 0x9248; - lsr = (lsr >> 3) | (lsr << 13); - _random_lsr = lsr; - set_mplex((_start & lsr) | 0x180); - _forced_level = -_forced_level; - break; - } -} - -void Player_V1::parsePCjrChunk() { - uint tmp; - uint i; - - set_mplex(3000); - _forced_level = 0; - -parse_again: - - _chunk_type = READ_LE_UINT16(_next_chunk); - debug(6, "parsePCjrChunk: sound %d, offset %4lx, chunk %x", - _current_nr, (long)(_next_chunk - _current_data), _chunk_type); - - _next_chunk += 2; - switch (_chunk_type) { - case 0xffff: - for (i = 0; i < 4; ++i) - clear_channel(i); - _current_nr = 0; - _current_data = 0; - _repeat_chunk = _next_chunk = 0; - chainNextSound(); - break; - - case 0xfffe: - _repeat_chunk = _next_chunk; - goto parse_again; - - case 0xfffd: - _next_chunk = _repeat_chunk; - goto parse_again; - - case 0xfffc: - /* handle reset. We don't need this do we? */ - goto parse_again; - - case 0: - set_mplex(READ_LE_UINT16(_next_chunk)); - _next_chunk += 2; - for (i = 0; i < 4; i++) { - tmp = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - if (tmp == 0xffff) { - _channels[i].cmd_ptr = 0; - continue; - } - _channels[i].attack = READ_LE_UINT16(_current_data + tmp); - _channels[i].decay = READ_LE_UINT16(_current_data + tmp + 2); - _channels[i].level = READ_LE_UINT16(_current_data + tmp + 4); - _channels[i].sustain_1 = READ_LE_UINT16(_current_data + tmp + 6); - _channels[i].sustain_2 = READ_LE_UINT16(_current_data + tmp + 8); - _channels[i].notelen = 1; - _channels[i].volume = 15; - _channels[i].cmd_ptr = _current_data + tmp + 10; - } - break; - - case 1: - set_mplex(READ_LE_UINT16(_next_chunk)); - tmp = READ_LE_UINT16(_next_chunk + 2); - _channels[0].cmd_ptr = tmp != 0xffff ? _current_data + tmp : NULL; - tmp = READ_LE_UINT16(_next_chunk + 4); - _start = READ_LE_UINT16(_next_chunk + 6); - _delta = (int16) READ_LE_UINT16(_next_chunk + 8); - _time_left = READ_LE_UINT16(_next_chunk + 10); - _next_chunk += 12; - if (tmp >= 0xe0) { - _channels[3].freq = tmp & 0xf; - _value_ptr = &_channels[3].volume; - } else { - assert(!(tmp & 0x10)); - tmp = (tmp & 0x60) >> 5; - _value_ptr = &_channels[tmp].freq; - _channels[tmp].volume = 0; - } - *_value_ptr = _start; - if (_channels[0].cmd_ptr) { - tmp = READ_LE_UINT16(_channels[0].cmd_ptr); - _start_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 2); - _delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 4); - _time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 6); - _channels[0].cmd_ptr += 8; - if (_value_ptr == &_channels[3].volume) { - tmp = (tmp & 0x70) >> 4; - if (tmp & 1) - _value_ptr_2 = &_channels[tmp >> 1].volume; - else - _value_ptr_2 = &_channels[tmp >> 1].freq; - } else { - assert(!(tmp & 0x10)); - tmp = (tmp & 0x60) >> 5; - _value_ptr_2 = &_channels[tmp].freq; - _channels[tmp].volume = 0; - } - *_value_ptr_2 = _start_2; - } - debug(6, "chunk 1: %lu: %d step %d for %d, %lu: %d step %d for %d", - (long)(_value_ptr - (uint *)_channels), _start, _delta, _time_left, - (long)(_value_ptr_2 - (uint *)_channels), _start_2, _delta_2, _time_left_2); - break; - - case 2: - _start = READ_LE_UINT16(_next_chunk); - _end = READ_LE_UINT16(_next_chunk + 2); - _delta = (int16) READ_LE_UINT16(_next_chunk + 4); - _channels[0].freq = 0; - _next_chunk += 6; - _forced_level = -1; - debug(6, "chunk 2: %d -> %d step %d", - _start, _end, _delta); - break; - case 3: - set_mplex(READ_LE_UINT16(_next_chunk)); - tmp = READ_LE_UINT16(_next_chunk + 2); - assert((tmp & 0xf0) == 0xe0); - _channels[3].freq = tmp & 0xf; - if ((tmp & 3) == 3) { - _next_chunk += 2; - _channels[2].freq = READ_LE_UINT16(_next_chunk + 2); - } - _channels[3].volume = READ_LE_UINT16(_next_chunk + 4); - _repeat_ctr = READ_LE_UINT16(_next_chunk + 6); - _delta = (int16) READ_LE_UINT16(_next_chunk + 8); - _next_chunk += 10; - break; - } -} - -void Player_V1::nextPCjrCmd() { - uint i; - int dummy; - switch (_chunk_type) { - case 0: - for (i = 0; i < 4; i++) { - if (!_channels[i].cmd_ptr) - continue; - if (!--_channels[i].notelen) { - dummy = READ_LE_UINT16(_channels[i].cmd_ptr); - if (dummy >= 0xfffe) { - if (dummy == 0xfffe) - _next_chunk = _current_data + 2; - parsePCjrChunk(); - return; - } - _channels[i].notelen = 4 * dummy; - dummy = READ_LE_UINT16(_channels[i].cmd_ptr + 2); - if (dummy == 0) { - _channels[i].hull_counter = 4; - _channels[i].sustctr = _channels[i].sustain_2; - } else { - _channels[i].hull_counter = 1; - _channels[i].freq = dummy; - } - debug(7, "chunk 0: channel %d play %d for %d", - i, dummy, _channels[i].notelen); - _channels[i].cmd_ptr += 4; - } - - - switch (_channels[i].hull_counter) { - case 1: - _channels[i].volume -= _channels[i].attack; - if ((int) _channels[i].volume <= 0) { - _channels[i].volume = 0; - _channels[i].hull_counter++; - } - break; - case 2: - _channels[i].volume += _channels[i].decay; - if (_channels[i].volume >= _channels[i].level) { - _channels[i].volume = _channels[i].level; - _channels[i].hull_counter++; - } - break; - case 4: - if (--_channels[i].sustctr < 0) { - _channels[i].sustctr = _channels[i].sustain_2; - _channels[i].volume += _channels[i].sustain_1; - if ((int) _channels[i].volume >= 15) { - _channels[i].volume = 15; - _channels[i].hull_counter++; - } - } - break; - } - } - break; - - case 1: - _start += _delta; - *_value_ptr = _start; - if (!--_time_left) { - _start = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - if (_start == 0xffff) { - parsePCjrChunk(); - return; - } - _delta = (int16) READ_LE_UINT16(_next_chunk); - _time_left = READ_LE_UINT16(_next_chunk + 2); - _next_chunk += 4; - *_value_ptr = _start; - } - - if (_channels[0].cmd_ptr) { - _start_2 += _delta_2; - *_value_ptr_2 = _start_2; - if (!--_time_left_2) { - _start_2 = READ_LE_UINT16(_channels[0].cmd_ptr); - if (_start_2 == 0xffff) { - _next_chunk = _channels[0].cmd_ptr + 2; - parsePCjrChunk(); - return; - } - _delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 2); - _time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 4); - _channels[0].cmd_ptr += 6; - } - } - break; - - case 2: - _start += _delta; - if (_start == _end) { - parsePCjrChunk(); - return; - } - set_mplex(_start); - debug(7, "chunk 2: mplex %d curve %d", _start, _forced_level); - _forced_level = -_forced_level; - break; - case 3: - dummy = _channels[3].volume + _delta; - if (dummy >= 15) { - _channels[3].volume = 15; - } else if (dummy <= 0) { - _channels[3].volume = 0; - } else { - _channels[3].volume = dummy; - break; - } - - if (!--_repeat_ctr) { - parsePCjrChunk(); - return; - } - _delta = READ_LE_UINT16(_next_chunk); - _next_chunk += 2; - break; - } -} - -void Player_V1::set_mplex(uint mplex) { - if (mplex == 0) - mplex = 65536; - _mplex = mplex; - _tick_len = _mplex_step * mplex; -} - -void Player_V1::nextTick() { - if (_next_chunk) { - if (_pcjr) - nextPCjrCmd(); - else - nextSpeakerCmd(); - } -} - -void Player_V1::generateSpkSamples(int16 *data, uint len) { - uint i; - - memset(data, 0, 2 * sizeof(int16) * len); - if (_channels[0].freq == 0) { - if (_forced_level) { - int sample = _forced_level * _volumetable[0]; - for (i = 0; i < len; i++) - data[2*i] = data[2*i+1] = sample; - debug(9, "speaker: %8x: forced one", _tick_len); - } else if (!_level) { - return; - } - } else { - squareGenerator(0, _channels[0].freq, 0, 0, data, len); - debug(9, "speaker: %8x: freq %d %.1f", _tick_len, - _channels[0].freq, 1193000.0 / _channels[0].freq); - } - lowPassFilter(data, len); -} - -void Player_V1::generatePCjrSamples(int16 *data, uint len) { - uint i, j; - uint freq, vol; - bool hasdata = false; - - memset(data, 0, 2 * sizeof(int16) * len); - - if (_forced_level) { - int sample = _forced_level * _volumetable[0]; - for (i = 0; i < len; i++) - data[2*i] = data[2*i+1] = sample; - hasdata = true; - debug(9, "channel[4]: %8x: forced one", _tick_len); - } - - for (i = 1; i < 3; i++) { - freq = _channels[i].freq; - if (freq) { - for (j = 0; j < i; j++) { - if (freq == _channels[j].freq) { - /* HACK: this channel is playing at - * the same frequency as another. - * Synchronize it to the same phase to - * prevent interference. - */ - _timer_count[i] = _timer_count[j]; - _timer_output ^= (1 << i) & - (_timer_output ^ _timer_output << (i - j)); - } - } - } - } - - for (i = 0; i < 4; i++) { - freq = _channels[i].freq; - vol = _channels[i].volume; - if (!_volumetable[_channels[i].volume]) { - _timer_count[i] -= len << FIXP_SHIFT; - if (_timer_count[i] < 0) - _timer_count[i] = 0; - } else if (i < 3) { - hasdata = true; - squareGenerator(i, freq, vol, 0, data, len); - debug(9, "channel[%d]: %8x: freq %d %.1f ; volume %d", - i, _tick_len, freq, 111860.0 / freq, vol); - } else { - int noiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE; - int n = (freq & 3); - - freq = (n == 3) ? 2 * (_channels[2].freq) : 1 << (5 + n); - hasdata = true; - squareGenerator(i, freq, vol, noiseFB, data, len); - debug(9, "channel[%d]: %x: noise freq %d %.1f ; volume %d", - i, _tick_len, freq, 111860.0 / freq, vol); - } - } - - if (_level || hasdata) - lowPassFilter(data, len); -} - -} // End of namespace Scumm |