aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorJochen Hoenicke2003-08-14 19:41:40 +0000
committerJochen Hoenicke2003-08-14 19:41:40 +0000
commitfa457b95c107838f11728c84fc1e97779adcdfdb (patch)
tree2ab271bdbb717c9afc2aea804cdbf0e60e4f42e4 /scumm
parent5922f4c3d432a0698263b0afded5ae4ebb245340 (diff)
downloadscummvm-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.cpp495
-rw-r--r--scumm/player_v1.h47
-rw-r--r--scumm/player_v2.cpp144
-rw-r--r--scumm/player_v2.h15
-rw-r--r--scumm/resource_v2.cpp5
-rw-r--r--scumm/scummvm.cpp4
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 = &current_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)