diff options
| author | Max Horn | 2010-10-25 16:42:24 +0000 | 
|---|---|---|
| committer | Max Horn | 2010-10-25 16:42:24 +0000 | 
| commit | 075919756fdc2f5edfec0734b1fe822d2a303ad4 (patch) | |
| tree | 061ad5860c191a2252832929cb46e9a9eb34efaf | |
| parent | d2a7a840c786d0ea0e08267b95da25f655a1f322 (diff) | |
| download | scummvm-rg350-075919756fdc2f5edfec0734b1fe822d2a303ad4.tar.gz scummvm-rg350-075919756fdc2f5edfec0734b1fe822d2a303ad4.tar.bz2 scummvm-rg350-075919756fdc2f5edfec0734b1fe822d2a303ad4.zip  | |
SCUMM: Move shared code of Player_V2 & Player_V2CMS to new common base class
svn-id: r53830
| -rw-r--r-- | engines/scumm/module.mk | 1 | ||||
| -rw-r--r-- | engines/scumm/player_nes.h | 2 | ||||
| -rw-r--r-- | engines/scumm/player_v2.cpp | 660 | ||||
| -rw-r--r-- | engines/scumm/player_v2.h | 93 | ||||
| -rw-r--r-- | engines/scumm/player_v2base.cpp | 657 | ||||
| -rw-r--r-- | engines/scumm/player_v2base.h | 148 | ||||
| -rw-r--r-- | engines/scumm/player_v2cms.cpp | 621 | ||||
| -rw-r--r-- | engines/scumm/player_v2cms.h | 55 | 
8 files changed, 837 insertions, 1400 deletions
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index cd89f5ffad..1a60564a9e 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -41,6 +41,7 @@ MODULE_OBJS := \  	player_v1.o \  	player_v2.o \  	player_v2a.o \ +	player_v2base.o \  	player_v2cms.o \  	player_v3a.o \  	player_v4a.o \ diff --git a/engines/scumm/player_nes.h b/engines/scumm/player_nes.h index b2eafb79b0..89292f7c24 100644 --- a/engines/scumm/player_nes.h +++ b/engines/scumm/player_nes.h @@ -75,8 +75,6 @@ private:  	void APU_writeControl(byte value);  	byte APU_readStatus(); -	void do_mix(int16 *buf, uint len); -  	ScummEngine *_vm;  	Audio::Mixer *_mixer;  	Audio::SoundHandle _soundHandle; diff --git a/engines/scumm/player_v2.cpp b/engines/scumm/player_v2.cpp index c1c9b3930e..60103b20fb 100644 --- a/engines/scumm/player_v2.cpp +++ b/engines/scumm/player_v2.cpp @@ -23,8 +23,6 @@   *   */ - -#include "engines/engine.h"  #include "scumm/player_v2.h"  #include "scumm/scumm.h"  #include "sound/mididrv.h" @@ -32,373 +30,51 @@  namespace Scumm { -#define FREQ_HZ 236 // Don't change! -  #define SPK_DECAY   0xa000              /* Depends on sample rate */  #define PCJR_DECAY  0xa000              /* Depends on sample rate */ -#define FIXP_SHIFT  16 -#define MAX_OUTPUT 0x7fff -  #define NG_PRESET 0x0f35        /* noise generator preset */  #define FB_WNOISE 0x12000       /* feedback for white noise */  #define FB_PNOISE 0x08000       /* feedback for periodic noise */ -const uint8 note_lengths[] = { -	0, -	0,  0,  2, -	0,  3,  4, -	5,  6,  8, -	9, 12, 16, -	18, 24, 32, -	36, 48, 64, -	72, 96 -}; - -static const uint16 hull_offsets[] = { -	0, 12, 24, 36, 48, 60, -	72, 88, 104, 120, 136, 256, -	152, 164, 180 -}; - -static const int16 hulls[] = { -	// hull 0 -	3, -1, 0, 0, 0, 0, 0, 0, -	0, -1, 0, 0, -	// hull 1 (staccato) -	3, -1, 0, 32, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 2 (legato) -	3, -1, 0, 0, 0, 0, 0, 0, -	0, 0, 0, 0, -	// hull 3 (staccatissimo) -	3, -1, 0, 2, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 4 -	3, -1, 0, 6, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 5 -	3, -1, 0, 16, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 6 -	(int16) 60000, -1, -1000, 20, 0, 0, 0, 0, -	(int16) 40000, -1, -5000,  5, 0, -1, 0, 0, -	// hull 7 -	(int16) 50000, -1, 0, 8, 30000, -1, 0, 0, -	28000, -1, -5000,  5, 0, -1, 0, 0, -	// hull 8 -	(int16) 60000, -1, -2000, 16, 0, 0, 0, 0, -	28000, -1, -6000,  5, 0, -1, 0, 0, -	// hull 9 -	(int16) 55000, -1,     0,  8, (int16) 35000, -1, 0, 0, -	(int16) 40000, -1, -2000, 10, 0, -1, 0, 0, -	// hull 10 -	(int16) 60000, -1,     0,  4, -2000, 8, 0, 0, -	(int16) 40000, -1, -6000,  5, 0, -1, 0, 0, -	// hull 12 -	0, -1,   150, 340, -150, 340, 0, -1, -	0, -1, 0, 0, -	// hull 13  == 164 -	20000, -1,  4000,  7, 1000, 15, 0, 0, -	(int16) 35000, -1, -2000, 15, 0, -1, 0, 0, - -	// hull 14  == 180 -	(int16) 35000, -1,   500, 20, 0,  0, 0, 0, -	(int16) 45000, -1,  -500, 60, 0, -1, 0, 0, - -	// hull misc = 196 -	(int16) 44000, -1, -4400, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, -5300, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, -6300, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, -1375, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, -1656, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	// hull 11 == 256 -	(int16) 63000, -1, -1968, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, - 733, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, - 883, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, -1050, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, - 488, 90, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, - 588, 90, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, - 700, 90, 0, -1, 0, 0, -	0, -1, 0, 0 -}; - -static const uint16 freqmod_lengths[] = { -	0x1000, 0x1000, 0x20, 0x2000, 0x1000 -}; - -static const uint16 freqmod_offsets[] = { -	0, 0x100, 0x200, 0x302, 0x202 -}; - -static const int8 freqmod_table[0x502] = { -     0,   3,   6,   9,  12,  15,  18,  21, -    24,  27,  30,  33,  36,  39,  42,  45, -    48,  51,  54,  57,  59,  62,  65,  67, -    70,  73,  75,  78,  80,  82,  85,  87, -    89,  91,  94,  96,  98, 100, 102, 103, -   105, 107, 108, 110, 112, 113, 114, 116, -   117, 118, 119, 120, 121, 122, 123, 123, -   124, 125, 125, 126, 126, 126, 126, 126, -   126, 126, 126, 126, 126, 126, 125, 125, -   124, 123, 123, 122, 121, 120, 119, 118, -   117, 116, 114, 113, 112, 110, 108, 107, -   105, 103, 102, 100,  98,  96,  94,  91, -    89,  87,  85,  82,  80,  78,  75,  73, -    70,  67,  65,  62,  59,  57,  54,  51, -    48,  45,  42,  39,  36,  33,  30,  27, -    24,  21,  18,  15,  12,   9,   6,   3, -     0,  -3,  -6,  -9, -12, -15, -18, -21, -   -24, -27, -30, -33, -36, -39, -42, -45, -   -48, -51, -54, -57, -59, -62, -65, -67, -   -70, -73, -75, -78, -80, -82, -85, -87, -   -89, -91, -94, -96, -98,-100,-102,-103, -  -105,-107,-108,-110,-112,-113,-114,-116, -  -117,-118,-119,-120,-121,-122,-123,-123, -  -124,-125,-125,-126,-126,-126,-126,-126, -  -126,-126,-126,-126,-126,-126,-125,-125, -  -124,-123,-123,-122,-121,-120,-119,-118, -  -117,-116,-114,-113,-112,-110,-108,-107, -  -105,-103,-102,-100, -98, -96, -94, -91, -   -89, -87, -85, -82, -80, -78, -75, -73, -   -70, -67, -65, -62, -59, -57, -54, -51, -   -48, -45, -42, -39, -36, -33, -30, -27, -   -24, -21, -18, -15, -12,  -9,  -6,  -3, - -     0,   1,   2,   3,   4,   5,   6,   7, -     8,   9,  10,  11,  12,  13,  14,  15, -    16,  17,  18,  19,  20,  21,  22,  23, -    24,  25,  26,  27,  28,  29,  30,  31, -    32,  33,  34,  35,  36,  37,  38,  39, -    40,  41,  42,  43,  44,  45,  46,  47, -    48,  49,  50,  51,  52,  53,  54,  55, -    56,  57,  58,  59,  60,  61,  62,  63, -    64,  65,  66,  67,  68,  69,  70,  71, -    72,  73,  74,  75,  76,  77,  78,  79, -    80,  81,  82,  83,  84,  85,  86,  87, -    88,  89,  90,  91,  92,  93,  94,  95, -    96,  97,  98,  99, 100, 101, 102, 103, -   104, 105, 106, 107, 108, 109, 110, 111, -   112, 113, 114, 115, 116, 117, 118, 119, -   120, 121, 122, 123, 124, 125, 126, 127, -  -128,-127,-126,-125,-124,-123,-122,-121, -  -120,-119,-118,-117,-116,-115,-114,-113, -  -112,-111,-110,-109,-108,-107,-106,-105, -  -104,-103,-102,-101,-100, -99, -98, -97, -   -96, -95, -94, -93, -92, -91, -90, -89, -   -88, -87, -86, -85, -84, -83, -82, -81, -   -80, -79, -78, -77, -76, -75, -74, -73, -   -72, -71, -70, -69, -68, -67, -66, -65, -   -64, -63, -62, -61, -60, -59, -58, -57, -   -56, -55, -54, -53, -52, -51, -50, -49, -   -48, -47, -46, -45, -44, -43, -42, -41, -   -40, -39, -38, -37, -36, -35, -34, -33, -   -32, -31, -30, -29, -28, -27, -26, -25, -   -24, -23, -22, -21, -20, -19, -18, -17, -   -16, -15, -14, -13, -12, -11, -10,  -9, -    -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1, - -  -120, 120, - -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, - -    41,  35, -66,-124, -31, 108, -42, -82, -    82,-112,  73, -15, -15, -69, -23, -21, -   -77, -90, -37,  60,-121,  12,  62,-103, -    36,  94,  13,  28,   6, -73,  71, -34, -   -77,  18,  77, -56,  67, -69,-117, -90, -    31,   3,  90, 125,   9,  56,  37,  31, -    93, -44, -53,  -4,-106, -11,  69,  59, -    19,  13,-119,  10,  28, -37, -82,  50, -    32,-102,  80, -18,  64, 120,  54,  -3, -    18,  73,  50, -10, -98, 125,  73, -36, -   -83,  79,  20, -14,  68,  64, 102, -48, -   107, -60,  48, -73,  50,  59, -95,  34, -   -10,  34,-111, -99, -31,-117,  31, -38, -   -80, -54,-103,   2, -71, 114, -99,  73, -    44,-128, 126, -59,-103, -43, -23,-128, -   -78, -22, -55, -52,  83, -65, 103, -42, -   -65,  20, -42, 126,  45, -36,-114, 102, -  -125, -17,  87,  73,  97,  -1, 105,-113, -    97, -51, -47,  30, -99,-100,  22, 114, -   114, -26,  29, -16,-124,  79,  74, 119, -     2, -41, -24,  57,  44,  83, -53, -55, -    18,  30,  51, 116, -98,  12, -12, -43, -   -44, -97, -44, -92,  89, 126,  53, -49, -    50,  34, -12, -52, -49, -45,-112,  45, -    72, -45,-113, 117, -26, -39,  29,  42, -   -27, -64,  -9,  43, 120,-127,-121,  68, -    14,  95,  80,   0, -44,  97,-115, -66, -   123,   5,  21,   7,  59,  51,-126,  31, -    24, 112,-110, -38, 100,  84, -50, -79, -  -123,  62, 105,  21,  -8,  70, 106,   4, -  -106, 115,  14, -39,  22,  47, 103, 104, -   -44,  -9,  74,  74, -48,  87, 104, 118, -    -6,  22, -69,  17, -83, -82,  36,-120, -   121,  -2,  82, -37,  37,  67, -27,  60, -   -12,  69, -45, -40,  40, -50,  11, -11, -   -59,  96,  89,  61,-105,  39,-118,  89, -   118,  45, -48, -62, -55, -51, 104, -44, -    73, 106, 121,  37,   8,  97,  64,  20, -   -79,  59, 106, -91,  17,  40, -63,-116, -   -42, -87,  11,-121,-105,-116,  47, -15, -    21,  29,-102,-107, -63,-101, -31, -64, -   126, -23, -88,-102, -89,-122, -62, -75, -    84, -65,-102, -25, -39,  35, -47,  85, -  -112,  56,  40, -47, -39, 108, -95, 102, -    94,  78, -31,  48,-100,  -2, -39, 113, -   -97, -30, -91, -30,  12,-101, -76,  71, -   101,  56,  42,  70,-119, -87,-126, 121, -   122, 118, 120, -62,  99, -79,  38, -33, -   -38,  41, 109,  62,  98, -32,-106,  18, -    52, -65,  57, -90,  63,-119,  94, -15, -   109,  14, -29, 108,  40, -95,  30,  32, -    29, -53, -62,   3,  63,  65,   7,-124, -    15,  20,   5, 101,  27,  40,  97, -55, -   -59, -25,  44,-114,  70,  54,   8, -36, -   -13, -88,-115,  -2, -66, -14, -21, 113, -    -1, -96, -48,  59, 117,   6,-116, 126, -  -121, 120, 115,  77, -48, -66,-126, -66, -   -37, -62,  70,  65,  43,-116,  -6,  48, -   127, 112, -16, -89,  84,-122,  50,-107, -   -86,  91, 104,  19,  11, -26,  -4, -11, -   -54, -66, 125, -97,-119,-118,  65,  27, -    -3, -72,  79, 104, -10, 114, 123,  20, -  -103, -51, -45,  13, -16,  68,  58, -76, -   -90, 102,  83,  51,  11, -53, -95,  16 -}; - - -static const uint16  spk_freq_table[12] = { -	36484, 34436, 32503, 30679, 28957, 27332, -	25798, 24350, 22983, 21693, 20476, 19326 -}; - -static const uint16 pcjr_freq_table[12] = { -	65472, 61760, 58304, 55040, 52032, 49024, -	46272, 43648, 41216, 38912, 36736, 34624 -}; - - -Player_V2::Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr) { -	int i; - -	_isV3Game = (scumm->_game.version >= 3); -	_vm = scumm; -	_mixer = mixer; -	_sampleRate = _mixer->getOutputRate(); - -	_header_len = (scumm->_game.features & GF_OLD_BUNDLE) ? 4 : 6; -	// Initialize sound queue -	_current_nr = _next_nr = 0; -	_current_data = _next_data = 0; +Player_V2::Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr) +	: Player_V2Base(scumm, mixer, pcjr) { -	// Initialize channel code -	for (i = 0; i < 4; ++i) -		clear_channel(i); - -	_next_tick = 0; -	_tick_len = (_sampleRate << FIXP_SHIFT) / FREQ_HZ; - -	// Initialize V3 music timer -	_music_timer_ctr = _music_timer = 0; -	_ticks_per_music_timer = 65535; +	int i;  	// Initialize square generator  	_level = 0;  	_RNG = NG_PRESET; -	set_pcjr(pcjr); -	setMusicVolume(255); - -	_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); -} - -Player_V2::~Player_V2() { -	Common::StackLock lock(_mutex); -	_mixer->stopHandle(_soundHandle); -} - -void Player_V2::set_pcjr(bool pcjr) { -	Common::StackLock lock(_mutex); -  	_pcjr = pcjr;  	if (_pcjr) {  		_decay = PCJR_DECAY;  		_update_step = (_sampleRate << FIXP_SHIFT) / (111860 * 2); -		_freqs_table = pcjr_freq_table;  	} else {  		_decay = SPK_DECAY;  		_update_step = (_sampleRate << FIXP_SHIFT) / (1193000 * 2); -		_freqs_table = spk_freq_table;  	} -	/* adapt _decay to sample rate.  It must be squared when -	 * sample rate doubles. -	 */ -	int i; +	// Adapt _decay to sample rate.  It must be squared when +	// sample rate doubles.  	for (i = 0; (_sampleRate << i) < 30000; i++)  		_decay = _decay * _decay / 65536;  	_timer_output = 0;  	for (i = 0; i < 4; i++)  		_timer_count[i] = 0; + +	setMusicVolume(255); + +	_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +Player_V2::~Player_V2() { +	Common::StackLock lock(_mutex); +	_mixer->stopHandle(_soundHandle);  }  void Player_V2::setMusicVolume (int vol) { @@ -421,33 +97,6 @@ void Player_V2::setMusicVolume (int vol) {  	_volumetable[15] = 0;  } -void Player_V2::chainSound(int nr, byte *data) { -	int offset = _header_len + (_pcjr ? 10 : 2); - -	_current_nr = nr; -	_current_data = data; - -	for (int i = 0; i < 4; i++) { -		clear_channel(i); - -		_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; -		} -	} -	_music_timer = 0; -} - -void Player_V2::chainNextSound() { -	if (_next_nr) { -		chainSound(_next_nr, _next_data); -		_next_nr = 0; -		_next_data = 0; -	} -} -  void Player_V2::stopAllSounds() {  	Common::StackLock lock(_mutex); @@ -476,11 +125,11 @@ void Player_V2::stopSound(int nr) {  }  void Player_V2::startSound(int nr) { +	Common::StackLock lock(_mutex); +  	byte *data = _vm->getResourceAddress(rtSound, nr);  	assert(data); -	Common::StackLock lock(_mutex); -  	int cprio = _current_data ? *(_current_data + _header_len) : 0;  	int prio  = *(data + _header_len);  	int nprio = _next_data ? *(_next_data + _header_len) : 0; @@ -519,272 +168,11 @@ int Player_V2::getSoundStatus(int nr) const {  	return _current_nr == nr || _next_nr == nr;  } - -void Player_V2::clear_channel(int i) { -	ChannelInfo *channel = &_channels[i]; -	memset(channel, 0, sizeof(ChannelInfo)); -} - -int Player_V2::getMusicTimer() { -	if (_isV3Game) -		return _music_timer; -	else -		return _channels[0].d.music_timer; -} - -void Player_V2::execute_cmd(ChannelInfo *channel) { -	uint16 value; -	int16 offset; -	uint8 *script_ptr; -	ChannelInfo * current_channel; -	ChannelInfo * dest_channel; - -	current_channel = channel; - -	if (channel->d.next_cmd == 0) -		goto check_stopped; -	script_ptr = &_current_data[channel->d.next_cmd]; - -	for (;;) { -		uint8 opcode = *script_ptr++; -		if (opcode >= 0xf8) { -			switch (opcode) { -			case 0xf8: // set hull curve -				debug(7, "channels[%lu]: hull curve %2d", -				(long)(channel - _channels), *script_ptr); -				channel->d.hull_curve = hull_offsets[*script_ptr / 2]; -				script_ptr++; -				break; - -			case 0xf9: // set freqmod curve -				debug(7, "channels[%lu]: freqmod curve %2d", -				(long)(channel - _channels), *script_ptr); -				channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4]; -				channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4]; -				script_ptr++; -				break; - -			case 0xfd: // clear other channel -				value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo); -				debug(7, "clear channel %d", value); -				script_ptr += 2; -				// In Indy3, when traveling to Venice a command is -				// issued to clear channel 4. So we introduce a 4th -				// channel, which is never used.  All OOB accesses are -				// mapped to this channel. -				// -				// The original game had room for 8 channels, but only -				// channels 0-3 are read, changes to other channels -				// had no effect. -				if (value >= ARRAYSIZE (_channels)) -					value = 4; -				channel = &_channels[value]; -				// fall through - -			case 0xfa: // clear current channel -				if (opcode == 0xfa) -					debug(7, "clear channel"); -				channel->d.next_cmd   = 0; -				channel->d.base_freq  = 0; -				channel->d.freq_delta = 0; -				channel->d.freq = 0; -				channel->d.volume = 0; -				channel->d.volume_delta = 0; -				channel->d.inter_note_pause = 0; -				channel->d.transpose = 0; -				channel->d.hull_curve = 0; -				channel->d.hull_offset = 0; -				channel->d.hull_counter = 0; -				channel->d.freqmod_table = 0; -				channel->d.freqmod_offset = 0; -				channel->d.freqmod_incr = 0; -				channel->d.freqmod_multiplier = 0; -				channel->d.freqmod_modulo = 0; -				break; - -			case 0xfb: // ret from subroutine -				debug(7, "ret from sub"); -				script_ptr = _retaddr; -				break; - -			case 0xfc: // call subroutine -				offset = READ_LE_UINT16 (script_ptr); -				debug(7, "subroutine %d", offset); -				script_ptr += 2; -				_retaddr = script_ptr; -				script_ptr = _current_data + offset; -				break; - -			case 0xfe: // loop music -				opcode = *script_ptr++; -				offset = READ_LE_UINT16 (script_ptr); -				script_ptr += 2; -				debug(7, "loop if %d to %d", opcode, offset); -				if (!channel->array[opcode / 2] || --channel->array[opcode/2]) -					script_ptr += offset; -				break; - -			case 0xff: // set parameter -				opcode = *script_ptr++; -				value = READ_LE_UINT16 (script_ptr); -				channel->array[opcode / 2] = value; -				debug(7, "channels[%lu]: set param %2d = %5d", -						(long)(channel - _channels), opcode, value); -				script_ptr += 2; -				if (opcode == 14) { -				    /* tempo var */ -				    _ticks_per_music_timer = 125; -				} -				if (opcode == 0) -					goto end; -				break; -			} -		} else { // opcode < 0xf8 -			for (;;) { -				int16 note, octave; -				int is_last_note; -				dest_channel = &_channels[(opcode >> 5) & 3]; - -				if (!(opcode & 0x80)) { - -					int tempo = channel->d.tempo; -					if (!tempo) -						tempo = 1; -					channel->d.time_left = tempo * note_lengths[opcode & 0x1f]; - -					note = *script_ptr++; -					is_last_note = note & 0x80; -					note &= 0x7f; -					if (note == 0x7f) { -						debug(8, "channels[%lu]: pause %d", -							  (long)(channel - _channels), channel->d.time_left); -						goto end; -					} -				} else { - -					channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++; - -					if ((opcode & 0x10)) { -						debug(8, "channels[%lu]: pause %d", -							  (long)(channel - _channels), channel->d.time_left); -						goto end; -					} - -					is_last_note = 0; -					note = (*script_ptr++) & 0x7f; -				} - -				debug(8, "channels[%lu]: @%04lx note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", -						(long)(dest_channel - channel), (long)(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, -						is_last_note ? "last":""); - -				uint16 myfreq; -				dest_channel->d.time_left = channel->d.time_left; -				dest_channel->d.note_length = -					channel->d.time_left - dest_channel->d.inter_note_pause; -				note += dest_channel->d.transpose; -				while (note < 0) -					note += 12; -				octave = note / 12; -				note = note % 12; -				dest_channel->d.hull_offset = 0; -				dest_channel->d.hull_counter = 1; -				if (_pcjr && dest_channel == &_channels[3]) { -					dest_channel->d.hull_curve = 196 + note * 12; -					myfreq = 384 - 64 * octave; -				} else { -					myfreq = _freqs_table[note] >> octave; -				} -				dest_channel->d.freq = dest_channel->d.base_freq = myfreq; -				if (is_last_note) -					goto end; -				opcode = *script_ptr++; -			} -		} -	} - -end: -	channel = current_channel; -	if (channel->d.time_left) { -		channel->d.next_cmd = script_ptr - _current_data; -		return; -	} - -	channel->d.next_cmd = 0; - -check_stopped: -	int i; -	for (i = 0; i < 4; i++) { -		if (_channels[i].d.time_left) -			return; -	} - -	_current_nr = 0; -	_current_data = 0; -	chainNextSound(); -	return; -} - -void Player_V2::next_freqs(ChannelInfo *channel) { -	channel->d.volume    += channel->d.volume_delta; -	channel->d.base_freq += channel->d.freq_delta; - -	channel->d.freqmod_offset += channel->d.freqmod_incr; -	if (channel->d.freqmod_offset > channel->d.freqmod_modulo) -		channel->d.freqmod_offset -= channel->d.freqmod_modulo; -	channel->d.freq = -		(int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)]) -		* (int) channel->d.freqmod_multiplier / 256 -		+ channel->d.base_freq; - -	debug(9, "Freq: %d/%d, %d/%d/%d*%d %d", -			channel->d.base_freq, (int16)channel->d.freq_delta, -			channel->d.freqmod_table, channel->d.freqmod_offset, -			channel->d.freqmod_incr, channel->d.freqmod_multiplier, -			channel->d.freq); - -	if (channel->d.note_length && !--channel->d.note_length) { -		channel->d.hull_offset  = 16; -		channel->d.hull_counter = 1; -	} - -	if (!--channel->d.time_left) { -		execute_cmd(channel); -	} - -#if 0 -	debug(9, "channels[%d]: freq %d hull %d/%d/%d", -			channel - &_channels[0], channel->d.freq, -			channel->d.hull_curve, channel->d.hull_offset, -			channel->d.hull_counter); -#endif - -	if (channel->d.hull_counter && !--channel->d.hull_counter) { -		for (;;) { -			const int16 *hull_ptr = hulls -			+ channel->d.hull_curve + channel->d.hull_offset / 2; -			if (hull_ptr[1] == -1) { -				channel->d.volume = hull_ptr[0]; -				if (hull_ptr[0] == 0) -				channel->d.volume_delta = 0; -				channel->d.hull_offset += 4; -			} else { -				channel->d.volume_delta = hull_ptr[0]; -				channel->d.hull_counter = hull_ptr[1]; -				channel->d.hull_offset += 4; -				break; -			} -		} -	} -} - -void Player_V2::do_mix(int16 *data, uint len) { +int Player_V2::readBuffer(int16 *data, const int numSamples) {  	Common::StackLock lock(_mutex);  	uint step; +	uint len = numSamples / 2;  	do {  		if (!(_next_tick >> FIXP_SHIFT)) { @@ -802,18 +190,8 @@ void Player_V2::do_mix(int16 *data, uint len) {  		data += 2 * step;  		_next_tick -= step << FIXP_SHIFT;  	} while (len -= step); -} -void Player_V2::nextTick() { -	for (int i = 0; i < 4; i++) { -		if (!_channels[i].d.time_left) -			continue; -		next_freqs(&_channels[i]); -	} -	if (_music_timer_ctr++ >= _ticks_per_music_timer) { -		_music_timer_ctr = 0; -		_music_timer++; -	} +	return numSamples;  }  void Player_V2::lowPassFilter(int16 *sample, uint len) { diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h index 22a70f1b32..6a0b3d6d5e 100644 --- a/engines/scumm/player_v2.h +++ b/engines/scumm/player_v2.h @@ -26,84 +26,35 @@  #ifndef SCUMM_PLAYER_V2_H  #define SCUMM_PLAYER_V2_H -#include "common/scummsys.h" -#include "common/mutex.h" -#include "scumm/music.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" +#include "scumm/player_v2base.h"  namespace Scumm { -class ScummEngine; - -#include "common/pack-start.h"	// START STRUCT PACKING - -struct channel_data { -	uint16 time_left;          // 00 -	uint16 next_cmd;           // 02 -	uint16 base_freq;          // 04 -	uint16 freq_delta;         // 06 -	uint16 freq;               // 08 -	uint16 volume;             // 10 -	uint16 volume_delta;       // 12 -	uint16 tempo;              // 14 -	uint16 inter_note_pause;   // 16 -	uint16 transpose;          // 18 -	uint16 note_length;        // 20 -	uint16 hull_curve;         // 22 -	uint16 hull_offset;        // 24 -	uint16 hull_counter;       // 26 -	uint16 freqmod_table;      // 28 -	uint16 freqmod_offset;     // 30 -	uint16 freqmod_incr;       // 32 -	uint16 freqmod_multiplier; // 34 -	uint16 freqmod_modulo;     // 36 -	uint16 unknown[4];         // 38 - 44 -	uint16 music_timer;        // 46 -	uint16 music_script_nr;    // 48 -} PACKED_STRUCT; - -#include "common/pack-end.h"	// END STRUCT PACKING - -  /**   * Scumm V2 PC-Speaker MIDI driver.   * This simulates the pc speaker sound, which is driven  by the 8253 (square   * wave generator) and a low-band filter.   */ -class Player_V2 : public Audio::AudioStream, public MusicEngine { +class Player_V2 : public Player_V2Base {  public:  	Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr);  	virtual ~Player_V2(); +	// MusicEngine API  	virtual void setMusicVolume(int vol);  	virtual void startSound(int sound);  	virtual void stopSound(int sound);  	virtual void stopAllSounds(); -	virtual int  getMusicTimer(); +//	virtual int  getMusicTimer();  	virtual int  getSoundStatus(int sound) const;  	// AudioStream API -	int readBuffer(int16 *buffer, const int numSamples) { -		do_mix(buffer, numSamples / 2); -		return numSamples; -	} +	int readBuffer(int16 *buffer, const int numSamples);  	bool isStereo() const { return true; }  	bool endOfData() const { return false; }  	int getRate() const { return _sampleRate; }  protected: -	bool _isV3Game; -	Audio::Mixer *_mixer; -	Audio::SoundHandle _soundHandle; -	ScummEngine *_vm; - -	bool _pcjr; -	int _header_len; - -	uint32 _sampleRate; -	uint32 _next_tick; -	uint32 _tick_len;  	unsigned int _update_step;  	unsigned int _decay;  	int _level; @@ -113,47 +64,13 @@ protected:  	int _timer_count[4];  	int _timer_output; -	int   _current_nr; -	byte *_current_data; -	int   _next_nr; -	byte *_next_data; -	byte *_retaddr; - -	Common::Mutex _mutex; - -private: -	union ChannelInfo { -		channel_data d; -		uint16 array[sizeof(channel_data)/2]; -	}; - -	int _music_timer; -	int _music_timer_ctr; -	int _ticks_per_music_timer; - -	const uint16 *_freqs_table; - -	ChannelInfo _channels[5]; -  protected: -	virtual void nextTick(); -	virtual void clear_channel(int i); -	virtual void chainSound(int nr, byte *data); -	virtual void chainNextSound(); -  	virtual void generateSpkSamples(int16 *data, uint len);  	virtual void generatePCjrSamples(int16 *data, uint len);  	void lowPassFilter(int16 *data, uint len);  	void squareGenerator(int channel, int freq, int vol,  						int noiseFeedback, int16 *sample, uint len); - -private: -	void do_mix(int16 *buf, uint len); - -	void set_pcjr(bool pcjr); -	void execute_cmd(ChannelInfo *channel); -	void next_freqs(ChannelInfo *channel);  };  } // End of namespace Scumm diff --git a/engines/scumm/player_v2base.cpp b/engines/scumm/player_v2base.cpp new file mode 100644 index 0000000000..61c91aae85 --- /dev/null +++ b/engines/scumm/player_v2base.cpp @@ -0,0 +1,657 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "scumm/player_v2base.h" +#include "scumm/scumm.h" + +#define FREQ_HZ 236 // Don't change! + +#define MAX_OUTPUT 0x7fff + +namespace Scumm { + +const uint8 note_lengths[] = { +	0, +	0,  0,  2, +	0,  3,  4, +	5,  6,  8, +	9, 12, 16, +	18, 24, 32, +	36, 48, 64, +	72, 96 +}; + +static const uint16 hull_offsets[] = { +	0, 12, 24, 36, 48, 60, +	72, 88, 104, 120, 136, 256, +	152, 164, 180 +}; + +static const int16 hulls[] = { +	// hull 0 +	3, -1, 0, 0, 0, 0, 0, 0, +	0, -1, 0, 0, +	// hull 1 (staccato) +	3, -1, 0, 32, 0, -1, 0, 0, +	0, -1, 0, 0, +	// hull 2 (legato) +	3, -1, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, +	// hull 3 (staccatissimo) +	3, -1, 0, 2, 0, -1, 0, 0, +	0, -1, 0, 0, +	// hull 4 +	3, -1, 0, 6, 0, -1, 0, 0, +	0, -1, 0, 0, +	// hull 5 +	3, -1, 0, 16, 0, -1, 0, 0, +	0, -1, 0, 0, +	// hull 6 +	(int16) 60000, -1, -1000, 20, 0, 0, 0, 0, +	(int16) 40000, -1, -5000,  5, 0, -1, 0, 0, +	// hull 7 +	(int16) 50000, -1, 0, 8, 30000, -1, 0, 0, +	28000, -1, -5000,  5, 0, -1, 0, 0, +	// hull 8 +	(int16) 60000, -1, -2000, 16, 0, 0, 0, 0, +	28000, -1, -6000,  5, 0, -1, 0, 0, +	// hull 9 +	(int16) 55000, -1,     0,  8, (int16) 35000, -1, 0, 0, +	(int16) 40000, -1, -2000, 10, 0, -1, 0, 0, +	// hull 10 +	(int16) 60000, -1,     0,  4, -2000, 8, 0, 0, +	(int16) 40000, -1, -6000,  5, 0, -1, 0, 0, +	// hull 12 +	0, -1,   150, 340, -150, 340, 0, -1, +	0, -1, 0, 0, +	// hull 13  == 164 +	20000, -1,  4000,  7, 1000, 15, 0, 0, +	(int16) 35000, -1, -2000, 15, 0, -1, 0, 0, + +	// hull 14  == 180 +	(int16) 35000, -1,   500, 20, 0,  0, 0, 0, +	(int16) 45000, -1,  -500, 60, 0, -1, 0, 0, + +	// hull misc = 196 +	(int16) 44000, -1, -4400, 10, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 53000, -1, -5300, 10, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 63000, -1, -6300, 10, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 44000, -1, -1375, 32, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 53000, -1, -1656, 32, 0, -1, 0, 0, +	0, -1, 0, 0, + +	// hull 11 == 256 +	(int16) 63000, -1, -1968, 32, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 44000, -1, - 733, 60, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 53000, -1, - 883, 60, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 63000, -1, -1050, 60, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 44000, -1, - 488, 90, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 53000, -1, - 588, 90, 0, -1, 0, 0, +	0, -1, 0, 0, + +	(int16) 63000, -1, - 700, 90, 0, -1, 0, 0, +	0, -1, 0, 0 +}; + +static const uint16 freqmod_lengths[] = { +	0x1000, 0x1000, 0x20, 0x2000, 0x1000 +}; + +static const uint16 freqmod_offsets[] = { +	0, 0x100, 0x200, 0x302, 0x202 +}; + +static const int8 freqmod_table[0x502] = { +     0,   3,   6,   9,  12,  15,  18,  21, +    24,  27,  30,  33,  36,  39,  42,  45, +    48,  51,  54,  57,  59,  62,  65,  67, +    70,  73,  75,  78,  80,  82,  85,  87, +    89,  91,  94,  96,  98, 100, 102, 103, +   105, 107, 108, 110, 112, 113, 114, 116, +   117, 118, 119, 120, 121, 122, 123, 123, +   124, 125, 125, 126, 126, 126, 126, 126, +   126, 126, 126, 126, 126, 126, 125, 125, +   124, 123, 123, 122, 121, 120, 119, 118, +   117, 116, 114, 113, 112, 110, 108, 107, +   105, 103, 102, 100,  98,  96,  94,  91, +    89,  87,  85,  82,  80,  78,  75,  73, +    70,  67,  65,  62,  59,  57,  54,  51, +    48,  45,  42,  39,  36,  33,  30,  27, +    24,  21,  18,  15,  12,   9,   6,   3, +     0,  -3,  -6,  -9, -12, -15, -18, -21, +   -24, -27, -30, -33, -36, -39, -42, -45, +   -48, -51, -54, -57, -59, -62, -65, -67, +   -70, -73, -75, -78, -80, -82, -85, -87, +   -89, -91, -94, -96, -98,-100,-102,-103, +  -105,-107,-108,-110,-112,-113,-114,-116, +  -117,-118,-119,-120,-121,-122,-123,-123, +  -124,-125,-125,-126,-126,-126,-126,-126, +  -126,-126,-126,-126,-126,-126,-125,-125, +  -124,-123,-123,-122,-121,-120,-119,-118, +  -117,-116,-114,-113,-112,-110,-108,-107, +  -105,-103,-102,-100, -98, -96, -94, -91, +   -89, -87, -85, -82, -80, -78, -75, -73, +   -70, -67, -65, -62, -59, -57, -54, -51, +   -48, -45, -42, -39, -36, -33, -30, -27, +   -24, -21, -18, -15, -12,  -9,  -6,  -3, + +     0,   1,   2,   3,   4,   5,   6,   7, +     8,   9,  10,  11,  12,  13,  14,  15, +    16,  17,  18,  19,  20,  21,  22,  23, +    24,  25,  26,  27,  28,  29,  30,  31, +    32,  33,  34,  35,  36,  37,  38,  39, +    40,  41,  42,  43,  44,  45,  46,  47, +    48,  49,  50,  51,  52,  53,  54,  55, +    56,  57,  58,  59,  60,  61,  62,  63, +    64,  65,  66,  67,  68,  69,  70,  71, +    72,  73,  74,  75,  76,  77,  78,  79, +    80,  81,  82,  83,  84,  85,  86,  87, +    88,  89,  90,  91,  92,  93,  94,  95, +    96,  97,  98,  99, 100, 101, 102, 103, +   104, 105, 106, 107, 108, 109, 110, 111, +   112, 113, 114, 115, 116, 117, 118, 119, +   120, 121, 122, 123, 124, 125, 126, 127, +  -128,-127,-126,-125,-124,-123,-122,-121, +  -120,-119,-118,-117,-116,-115,-114,-113, +  -112,-111,-110,-109,-108,-107,-106,-105, +  -104,-103,-102,-101,-100, -99, -98, -97, +   -96, -95, -94, -93, -92, -91, -90, -89, +   -88, -87, -86, -85, -84, -83, -82, -81, +   -80, -79, -78, -77, -76, -75, -74, -73, +   -72, -71, -70, -69, -68, -67, -66, -65, +   -64, -63, -62, -61, -60, -59, -58, -57, +   -56, -55, -54, -53, -52, -51, -50, -49, +   -48, -47, -46, -45, -44, -43, -42, -41, +   -40, -39, -38, -37, -36, -35, -34, -33, +   -32, -31, -30, -29, -28, -27, -26, -25, +   -24, -23, -22, -21, -20, -19, -18, -17, +   -16, -15, -14, -13, -12, -11, -10,  -9, +    -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1, + +  -120, 120, + +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +  -120,-120,-120,-120,-120,-120,-120,-120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, +   120, 120, 120, 120, 120, 120, 120, 120, + +    41,  35, -66,-124, -31, 108, -42, -82, +    82,-112,  73, -15, -15, -69, -23, -21, +   -77, -90, -37,  60,-121,  12,  62,-103, +    36,  94,  13,  28,   6, -73,  71, -34, +   -77,  18,  77, -56,  67, -69,-117, -90, +    31,   3,  90, 125,   9,  56,  37,  31, +    93, -44, -53,  -4,-106, -11,  69,  59, +    19,  13,-119,  10,  28, -37, -82,  50, +    32,-102,  80, -18,  64, 120,  54,  -3, +    18,  73,  50, -10, -98, 125,  73, -36, +   -83,  79,  20, -14,  68,  64, 102, -48, +   107, -60,  48, -73,  50,  59, -95,  34, +   -10,  34,-111, -99, -31,-117,  31, -38, +   -80, -54,-103,   2, -71, 114, -99,  73, +    44,-128, 126, -59,-103, -43, -23,-128, +   -78, -22, -55, -52,  83, -65, 103, -42, +   -65,  20, -42, 126,  45, -36,-114, 102, +  -125, -17,  87,  73,  97,  -1, 105,-113, +    97, -51, -47,  30, -99,-100,  22, 114, +   114, -26,  29, -16,-124,  79,  74, 119, +     2, -41, -24,  57,  44,  83, -53, -55, +    18,  30,  51, 116, -98,  12, -12, -43, +   -44, -97, -44, -92,  89, 126,  53, -49, +    50,  34, -12, -52, -49, -45,-112,  45, +    72, -45,-113, 117, -26, -39,  29,  42, +   -27, -64,  -9,  43, 120,-127,-121,  68, +    14,  95,  80,   0, -44,  97,-115, -66, +   123,   5,  21,   7,  59,  51,-126,  31, +    24, 112,-110, -38, 100,  84, -50, -79, +  -123,  62, 105,  21,  -8,  70, 106,   4, +  -106, 115,  14, -39,  22,  47, 103, 104, +   -44,  -9,  74,  74, -48,  87, 104, 118, +    -6,  22, -69,  17, -83, -82,  36,-120, +   121,  -2,  82, -37,  37,  67, -27,  60, +   -12,  69, -45, -40,  40, -50,  11, -11, +   -59,  96,  89,  61,-105,  39,-118,  89, +   118,  45, -48, -62, -55, -51, 104, -44, +    73, 106, 121,  37,   8,  97,  64,  20, +   -79,  59, 106, -91,  17,  40, -63,-116, +   -42, -87,  11,-121,-105,-116,  47, -15, +    21,  29,-102,-107, -63,-101, -31, -64, +   126, -23, -88,-102, -89,-122, -62, -75, +    84, -65,-102, -25, -39,  35, -47,  85, +  -112,  56,  40, -47, -39, 108, -95, 102, +    94,  78, -31,  48,-100,  -2, -39, 113, +   -97, -30, -91, -30,  12,-101, -76,  71, +   101,  56,  42,  70,-119, -87,-126, 121, +   122, 118, 120, -62,  99, -79,  38, -33, +   -38,  41, 109,  62,  98, -32,-106,  18, +    52, -65,  57, -90,  63,-119,  94, -15, +   109,  14, -29, 108,  40, -95,  30,  32, +    29, -53, -62,   3,  63,  65,   7,-124, +    15,  20,   5, 101,  27,  40,  97, -55, +   -59, -25,  44,-114,  70,  54,   8, -36, +   -13, -88,-115,  -2, -66, -14, -21, 113, +    -1, -96, -48,  59, 117,   6,-116, 126, +  -121, 120, 115,  77, -48, -66,-126, -66, +   -37, -62,  70,  65,  43,-116,  -6,  48, +   127, 112, -16, -89,  84,-122,  50,-107, +   -86,  91, 104,  19,  11, -26,  -4, -11, +   -54, -66, 125, -97,-119,-118,  65,  27, +    -3, -72,  79, 104, -10, 114, 123,  20, +  -103, -51, -45,  13, -16,  68,  58, -76, +   -90, 102,  83,  51,  11, -53, -95,  16 +}; + +static const uint16  spk_freq_table[12] = { +	36484, 34436, 32503, 30679, 28957, 27332, +	25798, 24350, 22983, 21693, 20476, 19326 +}; + +static const uint16 pcjr_freq_table[12] = { +	65472, 61760, 58304, 55040, 52032, 49024, +	46272, 43648, 41216, 38912, 36736, 34624 +}; + + +Player_V2Base::Player_V2Base(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr) +	: _vm(scumm), +	_mixer(mixer), +	_pcjr(pcjr), +	_sampleRate(_mixer->getOutputRate()) { + +	_isV3Game = (scumm->_game.version >= 3); + +	_header_len = (scumm->_game.features & GF_OLD_BUNDLE) ? 4 : 6; + +	// Initialize sound queue +	_current_nr = _next_nr = 0; +	_current_data = _next_data = 0; + +	// Initialize channel code +	for (int i = 0; i < 4; ++i) +		clear_channel(i); + +	_next_tick = 0; +	_tick_len = (_sampleRate << FIXP_SHIFT) / FREQ_HZ; + +	// Initialize V3 music timer +	_music_timer_ctr = _music_timer = 0; +	_ticks_per_music_timer = 65535; + +	if (_pcjr) { +		_freqs_table = pcjr_freq_table; +	} else { +		_freqs_table = spk_freq_table; +	} +} + +Player_V2Base::~Player_V2Base() { +} + +void Player_V2Base::chainSound(int nr, byte *data) { +	int offset = _header_len + (_pcjr ? 10 : 2); + +	_current_nr = nr; +	_current_data = data; + +	for (int i = 0; i < 4; i++) { +		clear_channel(i); + +		_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; +			} +		} +	} +	_music_timer = 0; +} + +void Player_V2Base::chainNextSound() { +	if (_next_nr) { +		chainSound(_next_nr, _next_data); +		_next_nr = 0; +		_next_data = 0; +	} +} + +// TODO: Merge stopAllSounds, stopSound() and startSound(), using some overriding +// perhaps? Player_V2CMS's implementations start like that of Player_V2 +// but then add some MIDI related stuff. + +void Player_V2Base::clear_channel(int i) { +	ChannelInfo *channel = &_channels[i]; +	memset(channel, 0, sizeof(ChannelInfo)); +} + +int Player_V2Base::getMusicTimer() { +	if (_isV3Game) +		return _music_timer; +	else +		return _channels[0].d.music_timer; +} + +void Player_V2Base::execute_cmd(ChannelInfo *channel) { +	uint16 value; +	int16 offset; +	uint8 *script_ptr; +	ChannelInfo * current_channel; +	ChannelInfo * dest_channel; + +	current_channel = channel; + +	if (channel->d.next_cmd == 0) +		goto check_stopped; +	script_ptr = &_current_data[channel->d.next_cmd]; + +	for (;;) { +		uint8 opcode = *script_ptr++; +		if (opcode >= 0xf8) { +			switch (opcode) { +			case 0xf8: // set hull curve +				debug(7, "channels[%d]: hull curve %2d", +				(uint)(channel - _channels), *script_ptr); +				channel->d.hull_curve = hull_offsets[*script_ptr / 2]; +				script_ptr++; +				break; + +			case 0xf9: // set freqmod curve +				debug(7, "channels[%d]: freqmod curve %2d", +				(uint)(channel - _channels), *script_ptr); +				channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4]; +				channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4]; +				script_ptr++; +				break; + +			case 0xfd: // clear other channel +				value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo); +				debug(7, "clear channel %d", value); +				script_ptr += 2; +				// In Indy3, when traveling to Venice a command is +				// issued to clear channel 4. So we introduce a 4th +				// channel, which is never used.  All OOB accesses are +				// mapped to this channel. +				// +				// The original game had room for 8 channels, but only +				// channels 0-3 are read, changes to other channels +				// had no effect. +				if (value >= ARRAYSIZE (_channels)) +					value = 4; +				channel = &_channels[value]; +				// fall through + +			case 0xfa: // clear current channel +				if (opcode == 0xfa) +					debug(7, "clear channel"); +				channel->d.next_cmd   = 0; +				channel->d.base_freq  = 0; +				channel->d.freq_delta = 0; +				channel->d.freq = 0; +				channel->d.volume = 0; +				channel->d.volume_delta = 0; +				channel->d.inter_note_pause = 0; +				channel->d.transpose = 0; +				channel->d.hull_curve = 0; +				channel->d.hull_offset = 0; +				channel->d.hull_counter = 0; +				channel->d.freqmod_table = 0; +				channel->d.freqmod_offset = 0; +				channel->d.freqmod_incr = 0; +				channel->d.freqmod_multiplier = 0; +				channel->d.freqmod_modulo = 0; +				break; + +			case 0xfb: // ret from subroutine +				debug(7, "ret from sub"); +				script_ptr = _retaddr; +				break; + +			case 0xfc: // call subroutine +				offset = READ_LE_UINT16 (script_ptr); +				debug(7, "subroutine %d", offset); +				script_ptr += 2; +				_retaddr = script_ptr; +				script_ptr = _current_data + offset; +				break; + +			case 0xfe: // loop music +				opcode = *script_ptr++; +				offset = READ_LE_UINT16 (script_ptr); +				script_ptr += 2; +				debug(7, "loop if %d to %d", opcode, offset); +				if (!channel->array[opcode / 2] || --channel->array[opcode/2]) +					script_ptr += offset; +				break; + +			case 0xff: // set parameter +				opcode = *script_ptr++; +				value = READ_LE_UINT16 (script_ptr); +				channel->array[opcode / 2] = value; +				debug(7, "channels[%d]: set param %2d = %5d", +						(uint)(channel - _channels), opcode, value); +				script_ptr += 2; +				if (opcode == 14) { +				    /* tempo var */ +				    _ticks_per_music_timer = 125; +				} +				if (opcode == 0) +					goto end; +				break; +			} +		} else { // opcode < 0xf8 +			for (;;) { +				int16 note, octave; +				int is_last_note; +				dest_channel = &_channels[(opcode >> 5) & 3]; + +				if (!(opcode & 0x80)) { + +					int tempo = channel->d.tempo; +					if (!tempo) +						tempo = 1; +					channel->d.time_left = tempo * note_lengths[opcode & 0x1f]; + +					note = *script_ptr++; +					is_last_note = note & 0x80; +					note &= 0x7f; +					if (note == 0x7f) { +						debug(8, "channels[%d]: pause %d", +							  (uint)(channel - _channels), channel->d.time_left); +						goto end; +					} +				} else { + +					channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++; + +					if ((opcode & 0x10)) { +						debug(8, "channels[%d]: pause %d", +							  (uint)(channel - _channels), channel->d.time_left); +						goto end; +					} + +					is_last_note = 0; +					note = (*script_ptr++) & 0x7f; +				} + +				debug(8, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", +						(uint)(dest_channel - channel), script_ptr ? (uint)(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, +						is_last_note ? "last":""); + +				uint16 myfreq; +				dest_channel->d.time_left = channel->d.time_left; +				dest_channel->d.note_length = +					channel->d.time_left - dest_channel->d.inter_note_pause; +				note += dest_channel->d.transpose; +				while (note < 0) +					note += 12; +				octave = note / 12; +				note = note % 12; +				dest_channel->d.hull_offset = 0; +				dest_channel->d.hull_counter = 1; +				if (_pcjr && dest_channel == &_channels[3]) { +					dest_channel->d.hull_curve = 196 + note * 12; +					myfreq = 384 - 64 * octave; +				} else { +					myfreq = _freqs_table[note] >> octave; +				} +				dest_channel->d.freq = dest_channel->d.base_freq = myfreq; +				if (is_last_note) +					goto end; +				opcode = *script_ptr++; +			} +		} +	} + +end: +	channel = current_channel; +	if (channel->d.time_left) { +		channel->d.next_cmd = script_ptr - _current_data; +		return; +	} + +	channel->d.next_cmd = 0; + +check_stopped: +	int i; +	for (i = 0; i < 4; i++) { +		if (_channels[i].d.time_left) +			return; +	} + +	_current_nr = 0; +	_current_data = 0; +	chainNextSound(); +} + +void Player_V2Base::next_freqs(ChannelInfo *channel) { +	channel->d.volume    += channel->d.volume_delta; +	channel->d.base_freq += channel->d.freq_delta; + +	channel->d.freqmod_offset += channel->d.freqmod_incr; +	if (channel->d.freqmod_offset > channel->d.freqmod_modulo) +		channel->d.freqmod_offset -= channel->d.freqmod_modulo; + +	channel->d.freq = +		(int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)]) +		* (int) channel->d.freqmod_multiplier / 256 +		+ channel->d.base_freq; + +	debug(9, "Freq: %d/%d, %d/%d/%d*%d %d", +			channel->d.base_freq, (int16)channel->d.freq_delta, +			channel->d.freqmod_table, channel->d.freqmod_offset, +			channel->d.freqmod_incr, channel->d.freqmod_multiplier, +			channel->d.freq); + +	if (channel->d.note_length && !--channel->d.note_length) { +		channel->d.hull_offset  = 16; +		channel->d.hull_counter = 1; +	} + +	if (!--channel->d.time_left) { +		execute_cmd(channel); +	} + +	if (channel->d.hull_counter && !--channel->d.hull_counter) { +		for (;;) { +			const int16 *hull_ptr = hulls +			+ channel->d.hull_curve + channel->d.hull_offset / 2; +			if (hull_ptr[1] == -1) { +				channel->d.volume = hull_ptr[0]; +				if (hull_ptr[0] == 0) +				channel->d.volume_delta = 0; +				channel->d.hull_offset += 4; +			} else { +				channel->d.volume_delta = hull_ptr[0]; +				channel->d.hull_counter = hull_ptr[1]; +				channel->d.hull_offset += 4; +				break; +			} +		} +	} +} + +void Player_V2Base::nextTick() { +	for (int i = 0; i < 4; i++) { +		if (!_channels[i].d.time_left) +			continue; +		next_freqs(&_channels[i]); +	} +	if (_music_timer_ctr++ >= _ticks_per_music_timer) { +		_music_timer_ctr = 0; +		_music_timer++; +	} +} + + +} // End of namespace Scumm diff --git a/engines/scumm/player_v2base.h b/engines/scumm/player_v2base.h new file mode 100644 index 0000000000..7b90ae98cf --- /dev/null +++ b/engines/scumm/player_v2base.h @@ -0,0 +1,148 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCUMM_PLAYER_V2BASE_H +#define SCUMM_PLAYER_V2BASE_H + +#include "common/scummsys.h" +#include "common/mutex.h" +#include "scumm/music.h" +#include "sound/audiostream.h" +#include "sound/mixer.h" + +namespace Scumm { + +class ScummEngine; + + +#include "common/pack-start.h"	// START STRUCT PACKING + +struct channel_data { +	uint16 time_left;          // 00 +	uint16 next_cmd;           // 02 +	uint16 base_freq;          // 04 +	uint16 freq_delta;         // 06 +	uint16 freq;               // 08 +	uint16 volume;             // 10 +	uint16 volume_delta;       // 12 +	uint16 tempo;              // 14 +	uint16 inter_note_pause;   // 16 +	uint16 transpose;          // 18 +	uint16 note_length;        // 20 +	uint16 hull_curve;         // 22 +	uint16 hull_offset;        // 24 +	uint16 hull_counter;       // 26 +	uint16 freqmod_table;      // 28 +	uint16 freqmod_offset;     // 30 +	uint16 freqmod_incr;       // 32 +	uint16 freqmod_multiplier; // 34 +	uint16 freqmod_modulo;     // 36 +	uint16 unknown[4];         // 38 - 44 +	uint16 music_timer;        // 46 +	uint16 music_script_nr;    // 48 +} PACKED_STRUCT; + +#include "common/pack-end.h"	// END STRUCT PACKING + +/** + * Common base class for Player_V2 and Player_V2CMS. + */ +class Player_V2Base : public Audio::AudioStream, public MusicEngine { +public: +	Player_V2Base(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr); +	virtual ~Player_V2Base(); + +	// MusicEngine API +// 	virtual void setMusicVolume(int vol); +// 	virtual void startSound(int sound); +// 	virtual void stopSound(int sound); +// 	virtual void stopAllSounds(); + 	virtual int  getMusicTimer(); +// 	virtual int  getSoundStatus(int sound) const; + +	// AudioStream API +/* +	int readBuffer(int16 *buffer, const int numSamples) { +		do_mix(buffer, numSamples / 2); +		return numSamples; +	} +*/ +	bool isStereo() const { return true; } +	bool endOfData() const { return false; } +	int getRate() const { return _sampleRate; } + +protected: +	enum { +		FIXP_SHIFT = 16 +	}; + +	bool _isV3Game; +	Audio::Mixer *_mixer; +	Audio::SoundHandle _soundHandle; +	ScummEngine *_vm; + +	bool _pcjr; +	int _header_len; + +	const uint32 _sampleRate; +	uint32 _next_tick; +	uint32 _tick_len; + +	int   _current_nr; +	byte *_current_data; +	int   _next_nr; +	byte *_next_data; +	byte *_retaddr; + +	Common::Mutex _mutex; + +	union ChannelInfo { +		channel_data d; +		uint16 array[sizeof(channel_data)/2]; +	}; + +	ChannelInfo _channels[5]; + +private: +	int _music_timer; +	int _music_timer_ctr; +	int _ticks_per_music_timer; + +	const uint16 *_freqs_table; + +protected: +	virtual void nextTick(); +	virtual void clear_channel(int i); +	virtual void chainSound(int nr, byte *data); +	virtual void chainNextSound(); + +	void execute_cmd(ChannelInfo *channel); +	void next_freqs(ChannelInfo *channel); +}; + + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp index f11e475447..7bec171173 100644 --- a/engines/scumm/player_v2cms.cpp +++ b/engines/scumm/player_v2cms.cpp @@ -23,7 +23,6 @@   *   */ -#include "engines/engine.h"  #include "scumm/player_v2cms.h"  #include "scumm/scumm.h"  #include "sound/mididrv.h" @@ -32,15 +31,6 @@  namespace Scumm { -#define FREQ_HZ 236 // Don't change! - -#define FIXP_SHIFT  16 -#define MAX_OUTPUT 0x7fff - -#define NG_PRESET 0x0f35        /* noise generator preset */ -#define FB_WNOISE 0x12000       /* feedback for white noise */ -#define FB_PNOISE 0x08000       /* feedback for periodic noise */ -  #define PROCESS_ATTACK 1  #define PROCESS_RELEASE 2  #define PROCESS_SUSTAIN 3 @@ -49,283 +39,6 @@ namespace Scumm {  #define CMS_RATE 22050 -const uint8 note_lengths[] = { -	0, -	0,  0,  2, -	0,  3,  4, -	5,  6,  8, -	9, 12, 16, -	18, 24, 32, -	36, 48, 64, -	72, 96 -}; - -static const uint16 hull_offsets[] = { -	0, 12, 24, 36, 48, 60, -	72, 88, 104, 120, 136, 256, -	152, 164, 180 -}; - -static const int16 hulls[] = { -	// hull 0 -	3, -1, 0, 0, 0, 0, 0, 0, -	0, -1, 0, 0, -	// hull 1 (staccato) -	3, -1, 0, 32, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 2 (legato) -	3, -1, 0, 0, 0, 0, 0, 0, -	0, 0, 0, 0, -	// hull 3 (staccatissimo) -	3, -1, 0, 2, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 4 -	3, -1, 0, 6, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 5 -	3, -1, 0, 16, 0, -1, 0, 0, -	0, -1, 0, 0, -	// hull 6 -	(int16) 60000, -1, -1000, 20, 0, 0, 0, 0, -	(int16) 40000, -1, -5000,  5, 0, -1, 0, 0, -	// hull 7 -	(int16) 50000, -1, 0, 8, 30000, -1, 0, 0, -	28000, -1, -5000,  5, 0, -1, 0, 0, -	// hull 8 -	(int16) 60000, -1, -2000, 16, 0, 0, 0, 0, -	28000, -1, -6000,  5, 0, -1, 0, 0, -	// hull 9 -	(int16) 55000, -1,     0,  8, (int16) 35000, -1, 0, 0, -	(int16) 40000, -1, -2000, 10, 0, -1, 0, 0, -	// hull 10 -	(int16) 60000, -1,     0,  4, -2000, 8, 0, 0, -	(int16) 40000, -1, -6000,  5, 0, -1, 0, 0, -	// hull 12 -	0, -1,   150, 340, -150, 340, 0, -1, -	0, -1, 0, 0, -	// hull 13  == 164 -	20000, -1,  4000,  7, 1000, 15, 0, 0, -	(int16) 35000, -1, -2000, 15, 0, -1, 0, 0, - -	// hull 14  == 180 -	(int16) 35000, -1,   500, 20, 0,  0, 0, 0, -	(int16) 45000, -1,  -500, 60, 0, -1, 0, 0, - -	// hull misc = 196 -	(int16) 44000, -1, -4400, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, -5300, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, -6300, 10, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, -1375, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, -1656, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	// hull 11 == 256 -	(int16) 63000, -1, -1968, 32, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, - 733, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, - 883, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, -1050, 60, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 44000, -1, - 488, 90, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 53000, -1, - 588, 90, 0, -1, 0, 0, -	0, -1, 0, 0, - -	(int16) 63000, -1, - 700, 90, 0, -1, 0, 0, -	0, -1, 0, 0 -}; - -static const uint16 freqmod_lengths[] = { -	0x1000, 0x1000, 0x20, 0x2000, 0x1000 -}; - -static const uint16 freqmod_offsets[] = { -	0, 0x100, 0x200, 0x302, 0x202 -}; - -static const int8 freqmod_table[0x502] = { -     0,   3,   6,   9,  12,  15,  18,  21, -    24,  27,  30,  33,  36,  39,  42,  45, -    48,  51,  54,  57,  59,  62,  65,  67, -    70,  73,  75,  78,  80,  82,  85,  87, -    89,  91,  94,  96,  98, 100, 102, 103, -   105, 107, 108, 110, 112, 113, 114, 116, -   117, 118, 119, 120, 121, 122, 123, 123, -   124, 125, 125, 126, 126, 126, 126, 126, -   126, 126, 126, 126, 126, 126, 125, 125, -   124, 123, 123, 122, 121, 120, 119, 118, -   117, 116, 114, 113, 112, 110, 108, 107, -   105, 103, 102, 100,  98,  96,  94,  91, -    89,  87,  85,  82,  80,  78,  75,  73, -    70,  67,  65,  62,  59,  57,  54,  51, -    48,  45,  42,  39,  36,  33,  30,  27, -    24,  21,  18,  15,  12,   9,   6,   3, -     0,  -3,  -6,  -9, -12, -15, -18, -21, -   -24, -27, -30, -33, -36, -39, -42, -45, -   -48, -51, -54, -57, -59, -62, -65, -67, -   -70, -73, -75, -78, -80, -82, -85, -87, -   -89, -91, -94, -96, -98,-100,-102,-103, -  -105,-107,-108,-110,-112,-113,-114,-116, -  -117,-118,-119,-120,-121,-122,-123,-123, -  -124,-125,-125,-126,-126,-126,-126,-126, -  -126,-126,-126,-126,-126,-126,-125,-125, -  -124,-123,-123,-122,-121,-120,-119,-118, -  -117,-116,-114,-113,-112,-110,-108,-107, -  -105,-103,-102,-100, -98, -96, -94, -91, -   -89, -87, -85, -82, -80, -78, -75, -73, -   -70, -67, -65, -62, -59, -57, -54, -51, -   -48, -45, -42, -39, -36, -33, -30, -27, -   -24, -21, -18, -15, -12,  -9,  -6,  -3, - -     0,   1,   2,   3,   4,   5,   6,   7, -     8,   9,  10,  11,  12,  13,  14,  15, -    16,  17,  18,  19,  20,  21,  22,  23, -    24,  25,  26,  27,  28,  29,  30,  31, -    32,  33,  34,  35,  36,  37,  38,  39, -    40,  41,  42,  43,  44,  45,  46,  47, -    48,  49,  50,  51,  52,  53,  54,  55, -    56,  57,  58,  59,  60,  61,  62,  63, -    64,  65,  66,  67,  68,  69,  70,  71, -    72,  73,  74,  75,  76,  77,  78,  79, -    80,  81,  82,  83,  84,  85,  86,  87, -    88,  89,  90,  91,  92,  93,  94,  95, -    96,  97,  98,  99, 100, 101, 102, 103, -   104, 105, 106, 107, 108, 109, 110, 111, -   112, 113, 114, 115, 116, 117, 118, 119, -   120, 121, 122, 123, 124, 125, 126, 127, -  -128,-127,-126,-125,-124,-123,-122,-121, -  -120,-119,-118,-117,-116,-115,-114,-113, -  -112,-111,-110,-109,-108,-107,-106,-105, -  -104,-103,-102,-101,-100, -99, -98, -97, -   -96, -95, -94, -93, -92, -91, -90, -89, -   -88, -87, -86, -85, -84, -83, -82, -81, -   -80, -79, -78, -77, -76, -75, -74, -73, -   -72, -71, -70, -69, -68, -67, -66, -65, -   -64, -63, -62, -61, -60, -59, -58, -57, -   -56, -55, -54, -53, -52, -51, -50, -49, -   -48, -47, -46, -45, -44, -43, -42, -41, -   -40, -39, -38, -37, -36, -35, -34, -33, -   -32, -31, -30, -29, -28, -27, -26, -25, -   -24, -23, -22, -21, -20, -19, -18, -17, -   -16, -15, -14, -13, -12, -11, -10,  -9, -    -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1, - -  -120, 120, - -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -  -120,-120,-120,-120,-120,-120,-120,-120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, -   120, 120, 120, 120, 120, 120, 120, 120, - -    41,  35, -66,-124, -31, 108, -42, -82, -    82,-112,  73, -15, -15, -69, -23, -21, -   -77, -90, -37,  60,-121,  12,  62,-103, -    36,  94,  13,  28,   6, -73,  71, -34, -   -77,  18,  77, -56,  67, -69,-117, -90, -    31,   3,  90, 125,   9,  56,  37,  31, -    93, -44, -53,  -4,-106, -11,  69,  59, -    19,  13,-119,  10,  28, -37, -82,  50, -    32,-102,  80, -18,  64, 120,  54,  -3, -    18,  73,  50, -10, -98, 125,  73, -36, -   -83,  79,  20, -14,  68,  64, 102, -48, -   107, -60,  48, -73,  50,  59, -95,  34, -   -10,  34,-111, -99, -31,-117,  31, -38, -   -80, -54,-103,   2, -71, 114, -99,  73, -    44,-128, 126, -59,-103, -43, -23,-128, -   -78, -22, -55, -52,  83, -65, 103, -42, -   -65,  20, -42, 126,  45, -36,-114, 102, -  -125, -17,  87,  73,  97,  -1, 105,-113, -    97, -51, -47,  30, -99,-100,  22, 114, -   114, -26,  29, -16,-124,  79,  74, 119, -     2, -41, -24,  57,  44,  83, -53, -55, -    18,  30,  51, 116, -98,  12, -12, -43, -   -44, -97, -44, -92,  89, 126,  53, -49, -    50,  34, -12, -52, -49, -45,-112,  45, -    72, -45,-113, 117, -26, -39,  29,  42, -   -27, -64,  -9,  43, 120,-127,-121,  68, -    14,  95,  80,   0, -44,  97,-115, -66, -   123,   5,  21,   7,  59,  51,-126,  31, -    24, 112,-110, -38, 100,  84, -50, -79, -  -123,  62, 105,  21,  -8,  70, 106,   4, -  -106, 115,  14, -39,  22,  47, 103, 104, -   -44,  -9,  74,  74, -48,  87, 104, 118, -    -6,  22, -69,  17, -83, -82,  36,-120, -   121,  -2,  82, -37,  37,  67, -27,  60, -   -12,  69, -45, -40,  40, -50,  11, -11, -   -59,  96,  89,  61,-105,  39,-118,  89, -   118,  45, -48, -62, -55, -51, 104, -44, -    73, 106, 121,  37,   8,  97,  64,  20, -   -79,  59, 106, -91,  17,  40, -63,-116, -   -42, -87,  11,-121,-105,-116,  47, -15, -    21,  29,-102,-107, -63,-101, -31, -64, -   126, -23, -88,-102, -89,-122, -62, -75, -    84, -65,-102, -25, -39,  35, -47,  85, -  -112,  56,  40, -47, -39, 108, -95, 102, -    94,  78, -31,  48,-100,  -2, -39, 113, -   -97, -30, -91, -30,  12,-101, -76,  71, -   101,  56,  42,  70,-119, -87,-126, 121, -   122, 118, 120, -62,  99, -79,  38, -33, -   -38,  41, 109,  62,  98, -32,-106,  18, -    52, -65,  57, -90,  63,-119,  94, -15, -   109,  14, -29, 108,  40, -95,  30,  32, -    29, -53, -62,   3,  63,  65,   7,-124, -    15,  20,   5, 101,  27,  40,  97, -55, -   -59, -25,  44,-114,  70,  54,   8, -36, -   -13, -88,-115,  -2, -66, -14, -21, 113, -    -1, -96, -48,  59, 117,   6,-116, 126, -  -121, 120, 115,  77, -48, -66,-126, -66, -   -37, -62,  70,  65,  43,-116,  -6,  48, -   127, 112, -16, -89,  84,-122,  50,-107, -   -86,  91, 104,  19,  11, -26,  -4, -11, -   -54, -66, 125, -97,-119,-118,  65,  27, -    -3, -72,  79, 104, -10, 114, 123,  20, -  -103, -51, -45,  13, -16,  68,  58, -76, -   -90, 102,  83,  51,  11, -53, -95,  16 -}; -  static const byte freqTable[] = {  	  3,  10,  17,  24,  31,  38,  45,  51,  	 58,  65,  71,  77,  83,  90,  96, 102, @@ -416,48 +129,17 @@ static const byte releaseRate[] = {  	 36,  56,  80, 100, 120, 140, 160, 255  }; -static const uint16 pcjr_freq_table[12] = { -	65472, 61760, 58304, 55040, 52032, 49024, -	46272, 43648, 41216, 38912, 36736, 34624 -}; -  static const byte volumeTable[] = {  	0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22,  	0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF  }; -Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer) { +Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer) +	: Player_V2Base(scumm, mixer, true) {  	int i; -	_isV3Game = (scumm->_game.version >= 3); -	_vm = scumm; -	_mixer = mixer; -//	debug("mixer rate: %d", _mixer->getOutputRate()); -	_sampleRate = CMS_RATE; - -	_header_len = (scumm->_game.features & GF_OLD_BUNDLE) ? 4 : 6; - -	// Initialize sound queue -	_current_nr = _next_nr = 0; -	_current_data = _next_data = 0; - -	// Initialize channel code -	for (i = 0; i < 4; ++i) -		clear_channel(i); - -	_next_tick = 0; -	_tick_len = (_sampleRate << FIXP_SHIFT) / FREQ_HZ; - -	// Initialize V3 music timer -	_music_timer_ctr = _music_timer = 0; -	_ticks_per_music_timer = 65535; -  	setMusicVolume(255); -	_timer_output = 0; -	for (i = 0; i < 4; i++) -		_timer_count[i] = 0; -  	memset(_cmsVoicesBase, 0, sizeof(Voice)*16);  	memset(_cmsVoices, 0, sizeof(Voice2)*8);  	memset(_cmsChips, 0, sizeof(MusicChip)*2); @@ -521,34 +203,6 @@ Player_V2CMS::~Player_V2CMS() {  void Player_V2CMS::setMusicVolume(int vol) {  } -void Player_V2CMS::chainSound(int nr, byte *data) { -	int offset = _header_len + 10; - -	_current_nr = nr; -	_current_data = data; - -	for (int i = 0; i < 4; i++) { -		clear_channel(i); - -		_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; -			} -		} -	} -	_music_timer = 0; -} - -void Player_V2CMS::chainNextSound() { -	if (_next_nr) { -		chainSound(_next_nr, _next_data); -		_next_nr = 0; -		_next_data = 0; -	} -} -  void Player_V2CMS::stopAllSounds() {  	Common::StackLock lock(_mutex); @@ -700,275 +354,6 @@ int Player_V2CMS::getSoundStatus(int nr) const {  	return _current_nr == nr || _next_nr == nr || _loadedMidiSong == nr;  } - -void Player_V2CMS::clear_channel(int i) { -	ChannelInfo *channel = &_channels[i]; -	memset(channel, 0, sizeof(ChannelInfo)); -} - -int Player_V2CMS::getMusicTimer() { -	if (_isV3Game) -		return _music_timer; -	else -		return _channels[0].d.music_timer; -} - -void Player_V2CMS::execute_cmd(ChannelInfo *channel) { -	uint16 value; -	int16 offset; -	uint8 *script_ptr; -	ChannelInfo * current_channel; -	ChannelInfo * dest_channel; - -	current_channel = channel; - -	if (channel->d.next_cmd == 0) -		goto check_stopped; -	script_ptr = &_current_data[channel->d.next_cmd]; - -	for (;;) { -		uint8 opcode = *script_ptr++; -		if (opcode >= 0xf8) { -			switch (opcode) { -			case 0xf8: // set hull curve -				debug(7, "channels[%d]: hull curve %2d", -				(uint)(channel - _channels), *script_ptr); -				channel->d.hull_curve = hull_offsets[*script_ptr / 2]; -				script_ptr++; -				break; - -			case 0xf9: // set freqmod curve -				debug(7, "channels[%d]: freqmod curve %2d", -				(uint)(channel - _channels), *script_ptr); -				channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4]; -				channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4]; -				script_ptr++; -				break; - -			case 0xfd: // clear other channel -				value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo); -				debug(7, "clear channel %d", value); -				script_ptr += 2; -				// In Indy3, when traveling to Venice a command is -				// issued to clear channel 4. So we introduce a 4th -				// channel, which is never used.  All OOB accesses are -				// mapped to this channel. -				// -				// The original game had room for 8 channels, but only -				// channels 0-3 are read, changes to other channels -				// had no effect. -				if (value >= ARRAYSIZE (_channels)) -					value = 4; -				channel = &_channels[value]; -				// fall through - -			case 0xfa: // clear current channel -				if (opcode == 0xfa) -					debug(7, "clear channel"); -				channel->d.next_cmd   = 0; -				channel->d.base_freq  = 0; -				channel->d.freq_delta = 0; -				channel->d.freq = 0; -				channel->d.volume = 0; -				channel->d.volume_delta = 0; -				channel->d.inter_note_pause = 0; -				channel->d.transpose = 0; -				channel->d.hull_curve = 0; -				channel->d.hull_offset = 0; -				channel->d.hull_counter = 0; -				channel->d.freqmod_table = 0; -				channel->d.freqmod_offset = 0; -				channel->d.freqmod_incr = 0; -				channel->d.freqmod_multiplier = 0; -				channel->d.freqmod_modulo = 0; -				break; - -			case 0xfb: // ret from subroutine -				debug(7, "ret from sub"); -				script_ptr = _retaddr; -				break; - -			case 0xfc: // call subroutine -				offset = READ_LE_UINT16 (script_ptr); -				debug(7, "subroutine %d", offset); -				script_ptr += 2; -				_retaddr = script_ptr; -				script_ptr = _current_data + offset; -				break; - -			case 0xfe: // loop music -				opcode = *script_ptr++; -				offset = READ_LE_UINT16 (script_ptr); -				script_ptr += 2; -				debug(7, "loop if %d to %d", opcode, offset); -				if (!channel->array[opcode / 2] || --channel->array[opcode/2]) -					script_ptr += offset; -				break; - -			case 0xff: // set parameter -				opcode = *script_ptr++; -				value = READ_LE_UINT16 (script_ptr); -				channel->array[opcode / 2] = value; -				debug(7, "channels[%d]: set param %2d = %5d", -						(uint)(channel - _channels), opcode, value); -				script_ptr += 2; -				if (opcode == 14) { -				    /* tempo var */ -				    _ticks_per_music_timer = 125; -				} -				if (opcode == 0) -					goto end; -				break; -			} -		} else { // opcode < 0xf8 -			for (;;) { -				int16 note, octave; -				int is_last_note; -				dest_channel = &_channels[(opcode >> 5) & 3]; - -				if (!(opcode & 0x80)) { - -					int tempo = channel->d.tempo; -					if (!tempo) -						tempo = 1; -					channel->d.time_left = tempo * note_lengths[opcode & 0x1f]; - -					note = *script_ptr++; -					is_last_note = note & 0x80; -					note &= 0x7f; -					if (note == 0x7f) { -						debug(8, "channels[%d]: pause %d", -							  (uint)(channel - _channels), channel->d.time_left); -						goto end; -					} -				} else { - -					channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++; - -					if ((opcode & 0x10)) { -						debug(8, "channels[%d]: pause %d", -							  (uint)(channel - _channels), channel->d.time_left); -						goto end; -					} - -					is_last_note = 0; -					note = (*script_ptr++) & 0x7f; -				} - -				debug(8, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", -						(uint)(dest_channel - channel), script_ptr ? (uint)(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, -						is_last_note ? "last":""); - -				uint16 myfreq; -				dest_channel->d.time_left = channel->d.time_left; -				dest_channel->d.note_length = -					channel->d.time_left - dest_channel->d.inter_note_pause; -				note += dest_channel->d.transpose; -				while (note < 0) -					note += 12; -				octave = note / 12; -				note = note % 12; -				dest_channel->d.hull_offset = 0; -				dest_channel->d.hull_counter = 1; -				if (dest_channel == &_channels[3]) { -					dest_channel->d.hull_curve = 196 + note * 12; -					myfreq = 384 - 64 * octave; -				} else { -					myfreq = pcjr_freq_table[note] >> octave; -				} -				dest_channel->d.freq = dest_channel->d.base_freq = myfreq; -				if (is_last_note) -					goto end; -				opcode = *script_ptr++; -			} -		} -	} - -end: -	channel = current_channel; -	if (channel->d.time_left) { -		channel->d.next_cmd = script_ptr - _current_data; -		return; -	} - -	channel->d.next_cmd = 0; - -check_stopped: -	int i; -	for (i = 0; i < 4; i++) { -		if (_channels[i].d.time_left) -			return; -	} - -	_current_nr = 0; -	_current_data = 0; -	chainNextSound(); -	return; -} - -void Player_V2CMS::next_freqs(ChannelInfo *channel) { -	channel->d.volume    += channel->d.volume_delta; -	channel->d.base_freq += channel->d.freq_delta; - -	channel->d.freqmod_offset += channel->d.freqmod_incr; -	if (channel->d.freqmod_offset != 0) -		if (channel->d.freqmod_offset > channel->d.freqmod_modulo) -			channel->d.freqmod_offset -= channel->d.freqmod_modulo; - -	channel->d.freq = -		(int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)]) -		* (int) channel->d.freqmod_multiplier / 256 -		+ channel->d.base_freq; - -	debug(9, "Freq: %d/%d, %d/%d/%d*%d %d", -			channel->d.base_freq, (int16)channel->d.freq_delta, -			channel->d.freqmod_table, channel->d.freqmod_offset, -			channel->d.freqmod_incr, channel->d.freqmod_multiplier, -			channel->d.freq); - -	if (channel->d.note_length && !--channel->d.note_length) { -		channel->d.hull_offset  = 16; -		channel->d.hull_counter = 1; -	} - -	if (!--channel->d.time_left) { -		execute_cmd(channel); -	} - -	if (channel->d.hull_counter && !--channel->d.hull_counter) { -		for (;;) { -			const int16 *hull_ptr = hulls -			+ channel->d.hull_curve + channel->d.hull_offset / 2; -			if (hull_ptr[1] == -1) { -				channel->d.volume = hull_ptr[0]; -				if (hull_ptr[0] == 0) -					channel->d.volume_delta = 0; -				channel->d.hull_offset += 4; -			} else { -				channel->d.volume_delta = hull_ptr[0]; -				channel->d.hull_counter = hull_ptr[1]; -				channel->d.hull_offset += 4; -				break; -			} -		} -	} -} - -void Player_V2CMS::nextTick() { -	for (int i = 0; i < 4; i++) { -		if (!_channels[i].d.time_left) -			continue; -		next_freqs(&_channels[i]); -	} -	if (_music_timer_ctr++ >= _ticks_per_music_timer) { -		_music_timer_ctr = 0; -		_music_timer++; -	} -} -  void Player_V2CMS::processMidiData(uint ticks) {  	byte *currentData = _midiData;  	byte command = 0x00; @@ -1029,7 +414,7 @@ int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) {  	Common::StackLock lock(_mutex);  	uint step = 1; -	int len = numSamples/2; +	int len = numSamples / 2;  	// maybe this needs a complete rewrite  	do { diff --git a/engines/scumm/player_v2cms.h b/engines/scumm/player_v2cms.h index 20640b1d60..fd939d8505 100644 --- a/engines/scumm/player_v2cms.h +++ b/engines/scumm/player_v2cms.h @@ -26,28 +26,26 @@  #ifndef SCUMM_PLAYER_V2CMS_H  #define SCUMM_PLAYER_V2CMS_H -#include "scumm/player_v2.h"	// for channel_data +#include "scumm/player_v2base.h"	// for channel_data  class CMSEmulator;  namespace Scumm { -class ScummEngine; - -  /**   * Scumm V2 CMS/Gameblaster MIDI driver.   */ -class Player_V2CMS : public Audio::AudioStream, public MusicEngine { +class Player_V2CMS : public Player_V2Base {  public:  	Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer);  	virtual ~Player_V2CMS(); +	// MusicEngine API  	virtual void setMusicVolume(int vol);  	virtual void startSound(int sound);  	virtual void stopSound(int sound);  	virtual void stopAllSounds(); -	virtual int  getMusicTimer(); +//	virtual int  getMusicTimer();  	virtual int  getSoundStatus(int sound) const;  	// AudioStream API @@ -159,53 +157,8 @@ protected:  	// from Player_V2  protected: -	bool _isV3Game; -	Audio::Mixer *_mixer; -	Audio::SoundHandle _soundHandle; -	ScummEngine *_vm; -  	CMSEmulator *_cmsEmu; -	int _header_len; - -	uint32 _sampleRate; -	uint32 _next_tick; -	uint32 _tick_len; - -	int _timer_count[4]; -	int _timer_output; - -	int   _current_nr; -	byte *_current_data; -	int   _next_nr; -	byte *_next_data; -	byte *_retaddr; - -	Common::Mutex _mutex; - -private: -	union ChannelInfo { -		channel_data d; -		uint16 array[sizeof(channel_data)/2]; -	}; - -	int _music_timer; -	int _music_timer_ctr; -	int _ticks_per_music_timer; - -	ChannelInfo _channels[5]; - -protected: -	virtual void nextTick(); -	virtual void clear_channel(int i); -	virtual void chainSound(int nr, byte *data); -	virtual void chainNextSound(); - -private: -	void do_mix(int16 *buf, uint len); - -	void execute_cmd(ChannelInfo *channel); -	void next_freqs(ChannelInfo *channel);  };  } // End of namespace Scumm  | 
