diff options
author | Jochen Hoenicke | 2003-08-14 19:41:40 +0000 |
---|---|---|
committer | Jochen Hoenicke | 2003-08-14 19:41:40 +0000 |
commit | fa457b95c107838f11728c84fc1e97779adcdfdb (patch) | |
tree | 2ab271bdbb717c9afc2aea804cdbf0e60e4f42e4 /scumm | |
parent | 5922f4c3d432a0698263b0afded5ae4ebb245340 (diff) | |
download | scummvm-rg350-fa457b95c107838f11728c84fc1e97779adcdfdb.tar.gz scummvm-rg350-fa457b95c107838f11728c84fc1e97779adcdfdb.tar.bz2 scummvm-rg350-fa457b95c107838f11728c84fc1e97779adcdfdb.zip |
Don't create imuse for v1 and v2 games (otherwise getSoundStatus doesn't work).
PCjr support for V1 games, bug fix in speaker support.
set_pcjr is now called by Player_V2 constructor according to midi driver.
Renaming of member variables to begin with an underscore.
svn-id: r9692
Diffstat (limited to 'scumm')
-rw-r--r-- | scumm/player_v1.cpp | 495 | ||||
-rw-r--r-- | scumm/player_v1.h | 47 | ||||
-rw-r--r-- | scumm/player_v2.cpp | 144 | ||||
-rw-r--r-- | scumm/player_v2.h | 15 | ||||
-rw-r--r-- | scumm/resource_v2.cpp | 5 | ||||
-rw-r--r-- | scumm/scummvm.cpp | 4 |
6 files changed, 497 insertions, 213 deletions
diff --git a/scumm/player_v1.cpp b/scumm/player_v1.cpp index 5bee75ca80..4d98413adb 100644 --- a/scumm/player_v1.cpp +++ b/scumm/player_v1.cpp @@ -22,7 +22,6 @@ #include "common/engine.h" #include "player_v1.h" #include "scumm.h" -#include "sound/mixer.h" #define TIMER_BASE_FREQ 1193000 #define FIXP_SHIFT 16 @@ -35,200 +34,400 @@ Player_V1::Player_V1(Scumm *scumm) : Player_V2(scumm) { - /* pcjr not yet supported */ - set_pcjr(false); + // Initialize channel code + for (int i = 0; i < 4; ++i) + clear_channel(i); - _freq_current = 0; + _mplex_step = (_sample_rate << FIXP_SHIFT) / 1193000; + _next_chunk = _repeat_chunk = 0; + _forced_level = 0; } Player_V1::~Player_V1() { } void Player_V1::chainSound(int nr, byte *data) { - int offset = _pcjr ? READ_LE_UINT16(data+4) : 6; + uint i; + for (i = 0; i < 4; ++i) + clear_channel(i); - current_nr = nr; - current_data = data; - _next_cmd = data + (_pcjr ? offset + 2 : offset + 4); - _repeat_ptr = _next_cmd; + _current_nr = nr; + _current_data = data; + _repeat_chunk = _next_chunk = data + (_pcjr ? 2 : 4); _music_timer = 0; debug(4, "Chaining new sound %d", nr); - parse_chunk(); + if (_pcjr) + parsePCjrChunk(); + else + parseSpeakerChunk(); } void Player_V1::startSound(int nr, byte *data) { mutex_up(); int offset = _pcjr ? READ_LE_UINT16(data+4) : 6; - int cprio = current_data ? *(current_data + offset) & 0x7f : 0; - int prio = *(data + _header_len) & 0x7f; - int nprio = next_data ? *(next_data + _header_len) & 0x7f : 0; - - int restartable = *(data + _header_len) & 0x80; - - if (!current_nr || cprio <= prio) { - int tnr = current_nr; - int tprio = cprio; - byte *tdata = current_data; - - chainSound(nr, data); - nr = tnr; - prio = tprio; - data = tdata; - restartable = data ? *(data + _header_len) & 0x80 : 0; - } - - if (!current_nr) { - nr = 0; - next_nr = 0; - next_data = 0; - } - - if (nr != current_nr - && restartable - && (!next_nr - || nprio <= prio)) { - - next_nr = nr; - next_data = data; + 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); } + mutex_down(); +} +void Player_V1::stopAllSounds() { + mutex_up(); + 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; mutex_down(); } -void Player_V1::restartSound() { - if (*(current_data + _header_len) & 0x80) { - /* current sound is restartable */ - chainSound(current_nr, current_data); - } else { +void Player_V1::stopSound(int nr) { + mutex_up(); + 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(); } + mutex_down(); +} + +void Player_V1::clear_channel(int i) { + _channels[i].freq = 0; + _channels[i].volume = 15; } int Player_V1::getMusicTimer() const { - return _music_timer; + /* Do V1 games have a music timer? */ + return 0; } -void Player_V1::parse_chunk() { +void Player_V1::parseSpeakerChunk() { set_mplex(3000); _forced_level = 0; parse_again: - _chunk_type = READ_LE_UINT16(_next_cmd); - debug(4, "parse_chunk: sound %d, offset %4x, chunk %x", - current_nr, _next_cmd - current_data, _chunk_type); + _chunk_type = READ_LE_UINT16(_next_chunk); + debug(6, "parseSpeakerChunk: sound %d, offset %4x, chunk %x", + _current_nr, _next_chunk - _current_data, _chunk_type); - _next_cmd += 2; + _next_chunk += 2; switch (_chunk_type) { case 0xffff: - current_nr = 0; - current_data = 0; - _freq_current = 0; + _current_nr = 0; + _current_data = 0; + _channels[0].freq = 0; + _next_chunk = 0; chainNextSound(); break; case 0xfffe: - _repeat_ptr = _next_cmd; + _repeat_chunk = _next_chunk; goto parse_again; case 0xfffd: - _next_cmd = _repeat_ptr; + _next_chunk = _repeat_chunk; goto parse_again; case 0xfffc: - /* handle reset. We don't need this don't we? */ + /* handle reset. We don't need this do we? */ goto parse_again; case 0: _time_left = 1; - set_mplex(READ_LE_UINT16(_next_cmd)); - _next_cmd += 2; + set_mplex(READ_LE_UINT16(_next_chunk)); + _next_chunk += 2; break; case 1: - set_mplex(READ_LE_UINT16(_next_cmd)); - _freq_start = READ_LE_UINT16(_next_cmd + 2); - _freq_end = READ_LE_UINT16(_next_cmd + 4); - _freq_delta = READ_LE_UINT16(_next_cmd + 6); - _repeat_ctr = READ_LE_UINT16(_next_cmd + 8); - _freq_current = _freq_start; - _next_cmd += 10; - debug(4, "chunk 1: mplex %d, freq %d -> %d step %d x %d", - _mplex, _freq_start, _freq_end, _freq_delta, _repeat_ctr); + 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: - _freq_start = READ_LE_UINT16(_next_cmd); - _freq_end = READ_LE_UINT16(_next_cmd + 2); - _freq_delta = READ_LE_UINT16(_next_cmd + 4); - _freq_current = 0; - _next_cmd += 6; - debug(4, "chunk 2: %d -> %d step %d", - _freq_start, _freq_end, _freq_delta); + _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; + debug(6, "chunk 2: %d -> %d step %d", + _start, _end, _delta); break; case 3: - _freq_start = READ_LE_UINT16(_next_cmd); - _freq_end = READ_LE_UINT16(_next_cmd + 2); - _freq_delta = READ_LE_UINT16(_next_cmd + 4); - _freq_current = 0; - _next_cmd += 6; - debug(4, "chunk 3: %d -> %d step %d", - _freq_start, _freq_end, _freq_delta); + _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; + debug(6, "chunk 3: %d -> %d step %d", + _start, _end, _delta); break; } } -void Player_V1::next_speaker_cmd() { +void Player_V1::nextSpeakerCmd() { uint16 lsr; switch (_chunk_type) { case 0: if (--_time_left) return; - _time_left = READ_LE_UINT16(_next_cmd); - _next_cmd += 2; + _time_left = READ_LE_UINT16(_next_chunk); + _next_chunk += 2; if (_time_left == 0xfffb) { /* handle 0xfffb?? */ - _time_left = READ_LE_UINT16(_next_cmd); - _next_cmd += 2; + _time_left = READ_LE_UINT16(_next_chunk); + _next_chunk += 2; } - debug(4, "next_speaker_cmd: chunk %d, offset %4x: notelen %d", - _chunk_type, _next_cmd - 2 - current_data, _time_left); + debug(7, "nextSpeakerCmd: chunk %d, offset %4x: notelen %d", + _chunk_type, _next_chunk - 2 - _current_data, _time_left); if (_time_left == 0) { - parse_chunk(); + parseSpeakerChunk(); } else { - _freq_current = READ_LE_UINT16(_next_cmd); - _next_cmd += 2; - debug(4, "freq_current: %d", _freq_current); + _channels[0].freq = READ_LE_UINT16(_next_chunk); + _next_chunk += 2; + debug(7, "freq_current: %d", _channels[0].freq); } break; case 1: - _freq_current = (_freq_current + _freq_delta) & 0xffff; - if (_freq_current == _freq_end) { - if (!--_repeat_ctr) - parse_chunk(); - _freq_current = _freq_start; + _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: - _freq_start = (_freq_start + _freq_delta) & 0xffff; - if (_freq_start == _freq_end) { - parse_chunk(); + _start = (_start + _delta) & 0xffff; + if (_start == _end) { + parseSpeakerChunk(); + return; } - set_mplex(_freq_start); + set_mplex(_start); _forced_level ^= 1; break; case 3: - _freq_start = (_freq_start + _freq_delta) & 0xffff; - if (_freq_start == _freq_end) { - parse_chunk(); + _start = (_start + _delta) & 0xffff; + if (_start == _end) { + parseSpeakerChunk(); + return; } lsr = _random_lsr + 0x9248; lsr = (lsr >> 3) | (lsr << 13); _random_lsr = lsr; - set_mplex((_freq_start & lsr) | 0x180); + set_mplex((_start & lsr) | 0x180); + _forced_level ^= 1; + 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 %4x, chunk %x", + _current_nr, _next_chunk - _current_data, _chunk_type); + + _next_chunk += 2; + switch (_chunk_type) { + case 1: /* FIXME: implement! */ + warning("Unimplemented PCjr chunk in sound %d:", _current_nr); + hexdump(_next_chunk-2, 160); + /* fall through*/ + 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 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; + 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: + 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 ^= 1; 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; } } @@ -236,8 +435,7 @@ void Player_V1::set_mplex (uint mplex) { if (mplex == 0) mplex = 65536; _mplex = mplex; - _tick_len = (_sample_rate << FIXP_SHIFT) - / (TIMER_BASE_FREQ / mplex); + _tick_len = _mplex_step * mplex; } void Player_V1::do_mix (int16 *data, uint len) { @@ -248,13 +446,21 @@ void Player_V1::do_mix (int16 *data, uint len) { step = len; if (step > (_next_tick >> FIXP_SHIFT)) step = (_next_tick >> FIXP_SHIFT); - generateSpkSamples(data, step); + if (_pcjr) + generatePCjrSamples(data, step); + else + generateSpkSamples(data, step); data += step; _next_tick -= step << FIXP_SHIFT; if (!(_next_tick >> FIXP_SHIFT)) { _next_tick += _tick_len; - next_speaker_cmd(); + if (_next_chunk) { + if (_pcjr) + nextPCjrCmd(); + else + nextSpeakerCmd(); + } } } while (len -= step); mutex_down(); @@ -264,16 +470,79 @@ void Player_V1::generateSpkSamples(int16 *data, uint len) { uint i; memset (data, 0, sizeof(int16) * len); - if (_freq_current == 0) { + if (_channels[0].freq == 0) { if (_forced_level) { for (i = 0; i < len; i++) { data[i] = _volumetable[0]; } + debug(9, "speaker: %8x: forced one", _tick_len); } else if (!_level) { return; } } else { - squareGenerator(0, _freq_current, 0, 0, data, len); + 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, sizeof(int16) * len); + + if (_forced_level) { + for (i = 0; i < len; i++) + data[i] = _volumetable[0]; + 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 (!freq || !_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); +} diff --git a/scumm/player_v1.h b/scumm/player_v1.h index 66d10c907c..6560078d83 100644 --- a/scumm/player_v1.h +++ b/scumm/player_v1.h @@ -25,39 +25,70 @@ #include "player_v2.h" +#define FB_WNOISE 0x12000 /* feedback for white noise */ +#define FB_PNOISE 0x08000 /* feedback for periodic noise */ + +struct channel_data_v1 { + uint freq; + uint volume; + byte *cmd_ptr; + uint notelen; + uint hull_counter; + uint attack; + uint decay; + uint level; + uint sustain_1; + uint sustain_2; + int sustctr; +}; + class Player_V1 : public Player_V2 { public: Player_V1(Scumm *scumm); ~Player_V1(); void startSound(int nr, byte *data); + void stopAllSounds(); + void stopSound(int nr); int getMusicTimer() const; protected: void restartSound(); void next_speaker_cmd(ChannelInfo *channel); + void clear_channel(int i); void chainSound(int nr, byte *data); void do_mix (int16 *buf, uint len); void set_mplex(uint mplex); - void parse_chunk(); - void next_speaker_cmd(); + void parseSpeakerChunk(); + void nextSpeakerCmd(); + void parsePCjrChunk(); + void nextPCjrCmd(); void generateSpkSamples(int16 *data, uint len); + void generatePCjrSamples(int16 *data, uint len); + + channel_data_v1 _channels[4]; private: - byte *_next_cmd; - byte *_repeat_ptr; + byte *_next_chunk; + byte *_repeat_chunk; uint _chunk_type; - uint _time_left; + uint _mplex_step; uint _mplex; - uint _freq_start; - uint _freq_end; - uint _freq_delta; uint _repeat_ctr; uint _freq_current; uint _forced_level; uint16 _random_lsr; + uint _channel; + uint _time_left; + uint _start; + uint _end; + int _delta; + uint _time_left_2; + uint _start_2; + int _delta_2; + uint _channel_2; }; #endif diff --git a/scumm/player_v2.cpp b/scumm/player_v2.cpp index b716733bfd..9c344c3dd4 100644 --- a/scumm/player_v2.cpp +++ b/scumm/player_v2.cpp @@ -22,6 +22,7 @@ #include "common/engine.h" #include "player_v2.h" #include "scumm.h" +#include "sound/mididrv.h" #include "sound/mixer.h" #define FREQ_HZ 236 // Don't change! @@ -342,8 +343,8 @@ Player_V2::Player_V2(Scumm *scumm) { _header_len = (scumm->_features & GF_OLD_BUNDLE) ? 4 : 6; // Initialize sound queue - current_nr = next_nr = 0; - current_data = next_data = 0; + _current_nr = _next_nr = 0; + _current_data = _next_data = 0; // Initialize channel code for (i = 0; i < 4; ++i) @@ -361,7 +362,7 @@ Player_V2::Player_V2(Scumm *scumm) { _RNG = NG_PRESET; - set_pcjr(true); + set_pcjr(scumm->_midiDriver != MD_PCSPK); set_master_volume(255); _mixer->setupPremix(this, premix_proc); @@ -401,8 +402,6 @@ void Player_V2::set_pcjr(bool pcjr) { for (i = 0; i < 4; i++) _timer_count[i] = 0; - if (current_data) - restartSound(); mutex_down(); } @@ -429,27 +428,27 @@ void Player_V2::set_master_volume (int vol) { void Player_V2::chainSound(int nr, byte *data) { int offset = _header_len + (_pcjr ? 10 : 2); - current_nr = nr; - current_data = data; + _current_nr = nr; + _current_data = data; for (int i = 0; i < 4; i++) { clear_channel(i); - channels[i].d.music_script_nr = nr; + _channels[i].d.music_script_nr = nr; if (data) { - channels[i].d.next_cmd = READ_LE_UINT16(data+offset+2*i); - if (channels[i].d.next_cmd) - channels[i].d.time_left = 1; + _channels[i].d.next_cmd = READ_LE_UINT16(data+offset+2*i); + if (_channels[i].d.next_cmd) + _channels[i].d.time_left = 1; } } _music_timer = 0; } void Player_V2::chainNextSound() { - if (next_nr) { - chainSound(next_nr, next_data); - next_nr = 0; - next_data = 0; + if (_next_nr) { + chainSound(_next_nr, _next_data); + _next_nr = 0; + _next_data = 0; } } @@ -458,23 +457,23 @@ void Player_V2::stopAllSounds() { for (int i = 0; i < 4; i++) { clear_channel(i); } - next_nr = current_nr = 0; - next_data = current_data = 0; + _next_nr = _current_nr = 0; + _next_data = _current_data = 0; mutex_down(); } void Player_V2::stopSound(int nr) { mutex_up(); - if (next_nr == nr) { - next_nr = 0; - next_data = 0; + if (_next_nr == nr) { + _next_nr = 0; + _next_data = 0; } - if (current_nr == nr) { + if (_current_nr == nr) { for (int i = 0; i < 4; i++) { clear_channel(i); } - current_nr = 0; - current_data = 0; + _current_nr = 0; + _current_data = 0; chainNextSound(); } mutex_down(); @@ -483,16 +482,16 @@ void Player_V2::stopSound(int nr) { void Player_V2::startSound(int nr, byte *data) { mutex_up(); - int cprio = current_data ? *(current_data + _header_len) : 0; + int cprio = _current_data ? *(_current_data + _header_len) : 0; int prio = *(data + _header_len); - int nprio = next_data ? *(next_data + _header_len) : 0; + int nprio = _next_data ? *(_next_data + _header_len) : 0; int restartable = *(data + _header_len + 1); - if (!current_nr || cprio <= prio) { - int tnr = current_nr; + if (!_current_nr || cprio <= prio) { + int tnr = _current_nr; int tprio = cprio; - byte *tdata = current_data; + byte *tdata = _current_data; chainSound(nr, data); nr = tnr; @@ -501,35 +500,26 @@ void Player_V2::startSound(int nr, byte *data) { restartable = data ? *(data + _header_len + 1) : 0; } - if (!current_nr) { + if (!_current_nr) { nr = 0; - next_nr = 0; - next_data = 0; + _next_nr = 0; + _next_data = 0; } - if (nr != current_nr + if (nr != _current_nr && restartable - && (!next_nr + && (!_next_nr || nprio <= prio)) { - next_nr = nr; - next_data = data; + _next_nr = nr; + _next_data = data; } mutex_down(); } -void Player_V2::restartSound() { - if (*(current_data + _header_len + 1)) { - /* current sound is restartable */ - chainSound(current_nr, current_data); - } else { - chainNextSound(); - } -} - bool Player_V2::getSoundStatus(int nr) const { - return current_nr == nr || next_nr == nr; + return _current_nr == nr || _next_nr == nr; } @@ -538,7 +528,7 @@ void Player_V2::premix_proc(void *param, int16 *buf, uint len) { } void Player_V2::clear_channel(int i) { - ChannelInfo *channel = &channels[i]; + ChannelInfo *channel = &_channels[i]; channel->d.time_left = 0; channel->d.next_cmd = 0; channel->d.base_freq = 0; @@ -563,7 +553,7 @@ int Player_V2::getMusicTimer() const { if (_isV3Game) return _music_timer; else - return channels[0].d.music_timer; + return _channels[0].d.music_timer; } void Player_V2::execute_cmd(ChannelInfo *channel) { @@ -577,7 +567,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { if (channel->d.next_cmd == 0) return; - script_ptr = ¤t_data[channel->d.next_cmd]; + script_ptr = &_current_data[channel->d.next_cmd]; for (;;) { uint8 opcode = *script_ptr++; @@ -585,14 +575,14 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { switch (opcode) { case 0xf8: // set hull curve debug(9, "channels[%d]: hull curve %2d", - channel - channels, *script_ptr); + channel - _channels, *script_ptr); channel->d.hull_curve = hull_offsets[*script_ptr/2]; script_ptr++; break; case 0xf9: // set freqmod curve debug(9, "channels[%d]: freqmod curve %2d", - channel - channels, *script_ptr); + channel - _channels, *script_ptr); channel->d.freqmod_table = freqmod_offsets[*script_ptr/4]; channel->d.freqmod_modulo = freqmod_lengths[*script_ptr/4]; script_ptr++; @@ -602,7 +592,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { value = READ_LE_UINT16 (script_ptr); debug(9, "clear channel %d", value/50); script_ptr += 2; - channel = &channels[value / sizeof(ChannelInfo)]; + channel = &_channels[value / sizeof(ChannelInfo)]; // fall through case 0xfa: // clear current channel @@ -628,15 +618,15 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { case 0xfb: // ret from subroutine debug(9, "ret from sub"); - script_ptr = retaddr; + script_ptr = _retaddr; break; case 0xfc: // call subroutine offset = READ_LE_UINT16 (script_ptr); debug(9, "subroutine %d", offset); script_ptr += 2; - retaddr = script_ptr; - script_ptr = current_data + offset; + _retaddr = script_ptr; + script_ptr = _current_data + offset; debug(9, "XXX1: %p -> %04x", script_ptr, offset); break; @@ -654,7 +644,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { value = READ_LE_UINT16 (script_ptr); channel->array[opcode/2] = value; debug(9, "channels[%d]: set param %2d = %5d", - channel - &channels[0], opcode, value); + channel - &_channels[0], opcode, value); script_ptr += 2; if (opcode == 14) { /* tempo var */ @@ -668,7 +658,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { for (;;) { int16 note, octave; int is_last_note; - dest_channel = &channels[(opcode >> 5) & 3]; + dest_channel = &_channels[(opcode >> 5) & 3]; if (!(opcode & 0x80)) { @@ -695,7 +685,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { debug(9, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", - dest_channel - channel, script_ptr ? script_ptr - current_data - 2 : 0, + dest_channel - channel, script_ptr ? script_ptr - _current_data - 2 : 0, note, (signed short) dest_channel->d.transpose, channel->d.time_left, dest_channel->d.hull_curve, dest_channel->d.freqmod_table, dest_channel->d.freqmod_incr,dest_channel->d.freqmod_multiplier, @@ -713,7 +703,7 @@ void Player_V2::execute_cmd(ChannelInfo *channel) { note = note % 12; dest_channel->d.hull_offset = 0; dest_channel->d.hull_counter = 1; - if (_pcjr && dest_channel == &channels[3]) { + if (_pcjr && dest_channel == &_channels[3]) { dest_channel->d.hull_curve = 180 + note * 12; myfreq = 384 - 64 * octave; } else { @@ -735,17 +725,17 @@ end: channel->d.next_cmd = 0; int i; for (i = 0; i< 4; i++) { - if (channels[i].d.time_left) + if (_channels[i].d.time_left) goto finish; } - current_nr = 0; - current_data = 0; + _current_nr = 0; + _current_data = 0; chainNextSound(); return; finish: - channel->d.next_cmd = script_ptr - current_data; + channel->d.next_cmd = script_ptr - _current_data; return; } @@ -778,7 +768,7 @@ void Player_V2::next_freqs(ChannelInfo *channel) { #if 0 debug(9, "channels[%d]: freq %d hull %d/%d/%d", - channel - &channels[0], channel->d.freq, + channel - &_channels[0], channel->d.freq, channel->d.hull_curve, channel->d.hull_offset, channel->d.hull_counter); #endif @@ -819,9 +809,9 @@ void Player_V2::do_mix (int16 *data, uint len) { if (!(_next_tick >> FIXP_SHIFT)) { for (int i = 0; i < 4; i++) { - if (!channels[i].d.time_left) + if (!_channels[i].d.time_left) continue; - next_freqs(&channels[i]); + next_freqs(&_channels[i]); } _next_tick += _tick_len; if (_music_timer_ctr++ >= _ticks_per_music_timer) { @@ -887,15 +877,15 @@ void Player_V2::generateSpkSamples(int16 *data, uint len) { int winning_channel = -1; for (int i = 0; i < 4; i++) { if (winning_channel == -1 - && channels[i].d.volume - && channels[i].d.time_left) { + && _channels[i].d.volume + && _channels[i].d.time_left) { winning_channel = i; } } memset (data, 0, sizeof(int16) * len); if (winning_channel != -1) { - squareGenerator(0, channels[winning_channel].d.freq, 0, + squareGenerator(0, _channels[winning_channel].d.freq, 0, 0, data, len); } else if (_level == 0) /* shortcut: no sound is being played. */ @@ -912,12 +902,12 @@ void Player_V2::generatePCjrSamples(int16 *data, uint len) { bool hasdata = false; for (i = 1; i < 3; i++) { - freq = channels[i].d.freq >> 6; - if (channels[i].d.volume && channels[i].d.time_left) { + freq = _channels[i].d.freq >> 6; + if (_channels[i].d.volume && _channels[i].d.time_left) { for (j = 0; j < i; j++) { - if (channels[j].d.volume - && channels[j].d.time_left - && freq == (channels[j].d.freq >> 6)) { + if (_channels[j].d.volume + && _channels[j].d.time_left + && freq == (_channels[j].d.freq >> 6)) { /* HACK: this channel is playing at * the same frequency as another. * Synchronize it to the same phase to @@ -932,9 +922,9 @@ void Player_V2::generatePCjrSamples(int16 *data, uint len) { } for (i = 0; i < 4; i++) { - freq = channels[i].d.freq >> 6; - vol = (65535 - channels[i].d.volume) >> 12; - if (!channels[i].d.volume || !channels[i].d.time_left) { + freq = _channels[i].d.freq >> 6; + vol = (65535 - _channels[i].d.volume) >> 12; + if (!_channels[i].d.volume || !_channels[i].d.time_left) { _timer_count[i] -= len << FIXP_SHIFT; if (_timer_count[i] < 0) _timer_count[i] = 0; @@ -945,7 +935,7 @@ void Player_V2::generatePCjrSamples(int16 *data, uint len) { int noiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE; int n = (freq & 3); - freq = (n == 3) ? 2 * (channels[2].d.freq>>6) : 1 << (5 + n); + freq = (n == 3) ? 2 * (_channels[2].d.freq>>6) : 1 << (5 + n); hasdata = true; squareGenerator(i, freq, vol, noiseFB, data, len); } diff --git a/scumm/player_v2.h b/scumm/player_v2.h index c023237ea6..680a6be9c6 100644 --- a/scumm/player_v2.h +++ b/scumm/player_v2.h @@ -75,7 +75,6 @@ public: Player_V2(Scumm *scumm); virtual ~Player_V2(); - virtual void set_pcjr(bool pcjr); virtual void set_master_volume(int vol); virtual void startSound(int nr, byte *data); @@ -109,19 +108,19 @@ protected: const uint16 *_freqs_table; - ChannelInfo channels[4]; + ChannelInfo _channels[4]; - int current_nr; - byte *current_data; - int next_nr; - byte *next_data; - byte *retaddr; + int _current_nr; + byte *_current_data; + int _next_nr; + byte *_next_data; + byte *_retaddr; OSystem::MutexRef _mutex; void mutex_up() { _system->lock_mutex (_mutex); } void mutex_down() { _system->unlock_mutex (_mutex); } - virtual void restartSound(); + virtual void set_pcjr(bool pcjr); void execute_cmd(ChannelInfo *channel); virtual void next_freqs(ChannelInfo *channel); virtual void clear_channel(int i); diff --git a/scumm/resource_v2.cpp b/scumm/resource_v2.cpp index dac033053e..431deb0708 100644 --- a/scumm/resource_v2.cpp +++ b/scumm/resource_v2.cpp @@ -109,11 +109,8 @@ void Scumm_v2::readClassicIndexFile() { void Scumm_v2::readEnhancedIndexFile() { //FIXME the music driver was previously been set before detection of classic/enchanced version. - if (!(_features & GF_AMIGA)) { + if (!(_features & GF_AMIGA)) _playerV2 = new Player_V2(this); - if (_midiDriver == MD_PCSPK) - _playerV2->set_pcjr(false); - } _numGlobalObjects = _fileHandle.readUint16LE(); _fileHandle.seek(_numGlobalObjects, SEEK_CUR); // Skip object flags diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index a1d4dd9fe7..9e428f5b4f 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -628,9 +628,7 @@ Scumm::Scumm (GameDetector *detector, OSystem *syst) _playerV2 = NULL; } else if (((_midiDriver == MD_PCJR) || (_midiDriver == MD_PCSPK)) && ((_version > 2) && (_version < 5))) { _playerV2 = new Player_V2(this); - if (_midiDriver == MD_PCSPK) - _playerV2->set_pcjr(false); - } else { + } else if (_version > 2) { _imuse = IMuse::create (syst, _mixer, detector->createMidi()); if (_imuse) { if (detector->_gameTempo != 0) |