diff options
author | Travis Howell | 2005-04-04 11:43:25 +0000 |
---|---|---|
committer | Travis Howell | 2005-04-04 11:43:25 +0000 |
commit | f230fe65e8b035d3bcbf3a45317cf56ac673fdfe (patch) | |
tree | 6de886f11751b849dfec6de3b695cd5410efba1d | |
parent | d08068dff1ea02314d791c1248d72091d4d5d9e9 (diff) | |
download | scummvm-rg350-f230fe65e8b035d3bcbf3a45317cf56ac673fdfe.tar.gz scummvm-rg350-f230fe65e8b035d3bcbf3a45317cf56ac673fdfe.tar.bz2 scummvm-rg350-f230fe65e8b035d3bcbf3a45317cf56ac673fdfe.zip |
Add 8 sound channel support for HE games
-Allows sound looping to work
Added support for WAVE format musuc used in later HE100 games.
svn-id: r17372
-rw-r--r-- | scumm/akos.cpp | 2 | ||||
-rw-r--r-- | scumm/script_v100he.cpp | 2 | ||||
-rw-r--r-- | scumm/script_v72he.cpp | 10 | ||||
-rw-r--r-- | scumm/script_v90he.cpp | 10 | ||||
-rw-r--r-- | scumm/sound.cpp | 90 | ||||
-rw-r--r-- | scumm/sound.h | 2 | ||||
-rw-r--r-- | scumm/wiz_he.cpp | 3 | ||||
-rw-r--r-- | sound/mixer.cpp | 8 | ||||
-rw-r--r-- | sound/mixer.h | 10 |
9 files changed, 88 insertions, 49 deletions
diff --git a/scumm/akos.cpp b/scumm/akos.cpp index 548a019e91..ca4b97f41a 100644 --- a/scumm/akos.cpp +++ b/scumm/akos.cpp @@ -1676,7 +1676,7 @@ void ScummEngine::akos_processQueue() { if (_features & GF_DIGI_IMUSE) _imuseDigital->startSfx(param_1, 63); else - _sound->addSoundToQueue(param_1); + _sound->addSoundToQueue(param_1, 0, -1, 0); } break; case 4: diff --git a/scumm/script_v100he.cpp b/scumm/script_v100he.cpp index 23e82fb8b0..61a12c95bc 100644 --- a/scumm/script_v100he.cpp +++ b/scumm/script_v100he.cpp @@ -311,7 +311,7 @@ void ScummEngine_v100he::setupOpcodes() { OPCODE(o6_isScriptRunning), OPCODE(o90_sin), /* D8 */ - OPCODE(o72_getSoundElapsedTimeOfSound), + OPCODE(o72_getSoundElapsedTime), OPCODE(o6_isSoundRunning), OPCODE(o80_getSoundVar), OPCODE(o100_getSpriteInfo), diff --git a/scumm/script_v72he.cpp b/scumm/script_v72he.cpp index e3a141f9e6..cb364fe0f0 100644 --- a/scumm/script_v72he.cpp +++ b/scumm/script_v72he.cpp @@ -156,7 +156,7 @@ void ScummEngine_v72he::setupOpcodes() { /* 58 */ OPCODE(o72_getTimer), OPCODE(o72_setTimer), - OPCODE(o72_getSoundElapsedTimeOfSound), + OPCODE(o72_getSoundElapsedTime), OPCODE(o6_wordArrayDec), /* 5C */ OPCODE(o6_if), @@ -562,6 +562,7 @@ void ScummEngine_v72he::decodeScriptString(byte *dst, bool scriptString) { switch(chr) { case 'b': // byte + error("decodeScriptString: byte unhandled"); break; case 'c': *dst++ = args[val--]; @@ -574,6 +575,7 @@ void ScummEngine_v72he::decodeScriptString(byte *dst, bool scriptString) { break; case 'x': // hexadecimal + error("decodeScriptString: hexadecimal unhandled"); break; default: error("decodeScriptString: Unknown type %d", chr); @@ -811,10 +813,10 @@ void ScummEngine_v72he::o72_setTimer() { } } -void ScummEngine_v72he::o72_getSoundElapsedTimeOfSound() { +void ScummEngine_v72he::o72_getSoundElapsedTime() { int snd = pop(); - push(_mixer->getSoundElapsedTimeOfSoundID(snd) * 10); - debug(1,"o72_getSoundElapsedTimeOfSound (%d)", snd); + push(_sound->getSoundElapsedTime(snd) * 10); + debug(1,"o72_getSoundElapsedTime (%d)", snd); } void ScummEngine_v72he::o72_startScript() { diff --git a/scumm/script_v90he.cpp b/scumm/script_v90he.cpp index 5430815225..a6040dbfff 100644 --- a/scumm/script_v90he.cpp +++ b/scumm/script_v90he.cpp @@ -153,7 +153,7 @@ void ScummEngine_v90he::setupOpcodes() { /* 58 */ OPCODE(o72_getTimer), OPCODE(o72_setTimer), - OPCODE(o72_getSoundElapsedTimeOfSound), + OPCODE(o72_getSoundElapsedTime), OPCODE(o6_wordArrayDec), /* 5C */ OPCODE(o6_if), @@ -746,7 +746,7 @@ void ScummEngine_v90he::o90_getSpriteInfo() { byte subOp = fetchScriptByte(); subOp -= 30; - debug(0,"o90_getSpriteInfo (%d)", subOp); + debug(1,"o90_getSpriteInfo (%d)", subOp); switch (subOp) { case 0: spriteId = pop(); @@ -1001,7 +1001,7 @@ void ScummEngine_v90he::o90_setSpriteInfo() { byte subOp = fetchScriptByte(); subOp -= 34; - debug(0,"o90_setSpriteInfo (%d)", subOp); + debug(1,"o90_setSpriteInfo (%d)", subOp); switch (subOp) { case 0: args[0] = pop(); @@ -1332,7 +1332,7 @@ void ScummEngine_v90he::o90_getSpriteGroupInfo() { byte subOp = fetchScriptByte(); - debug(0,"o90_getSpriteGroupInfo (%d)", subOp); + debug(1,"o90_getSpriteGroupInfo (%d)", subOp); switch (subOp) { case 8: // HE 99+ spriteGroupId = pop(); @@ -1414,7 +1414,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() { byte subOp = fetchScriptByte(); subOp -= 37; - debug(0,"o90_setSpriteGroupInfo (%d)", subOp); + debug(1,"o90_setSpriteGroupInfo (%d)", subOp); switch (subOp) { case 0: type = pop() - 1; diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 999e461450..fae0cc596c 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -33,12 +33,14 @@ #include "common/util.h" #include "sound/audiocd.h" +#include "sound/flac.h" #include "sound/mididrv.h" #include "sound/mixer.h" #include "sound/mp3.h" #include "sound/voc.h" #include "sound/vorbis.h" -#include "sound/flac.h" +#include "sound/wave.h" + namespace Scumm { @@ -159,6 +161,7 @@ void Sound::setOverrideFreq(int freq) { } void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { + debug(5,"playSound: soundID %d heOffset %d heChannel %d heFlags %d\n", soundID, heOffset, heChannel, heFlags); byte *mallocedPtr = NULL; byte *ptr; char *sound; @@ -166,6 +169,9 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { int rate; byte flags = SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE; + if (heChannel == -1) { + heChannel = 1; + } if (_vm->_heversion >= 70 && soundID > _vm->_numSounds) { debug(1, "playSound #%d", soundID); @@ -218,9 +224,7 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { size = musicFile.readUint32LE(); if (music_offs > total_size || (size + music_offs > total_size) || size < 0) { - warning("playSound: Invalid music offset (%d) in music %d", soundID); - musicFile.close(); - return; + error("playSound: Invalid music offset (%d) in music %d", soundID); } musicFile.seek(music_offs, SEEK_SET); @@ -231,7 +235,7 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { _vm->_mixer->stopID(_currentMusic); _currentMusic = soundID; if (_vm->_heversion == 70) { - _vm->_mixer->playRaw(NULL, ptr, size, 11025, flags, soundID); + _vm->_mixer->playRaw(&_heSoundChannels[heChannel], ptr, size, 11025, flags, soundID); return; } @@ -266,7 +270,18 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { } // Support for later Backyard sports games sounds else if (READ_UINT32(ptr) == MKID('RIFF')) { - // TODO: Play WAV, with set sound ID + size = READ_BE_UINT32(ptr + 4); + Common::MemoryReadStream stream(ptr, size); + + if (!loadWAVFromStream(stream, size, rate, flags)) { + warning("playSound: Not a valid WAV file"); + return; + } + + // Allocate a sound buffer, copy the data into it, and play + sound = (char *)malloc(size); + memcpy(sound, ptr + stream.pos(), size); + _vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); } // Support for Putt-Putt sounds - very hackish, too 8-) else if (READ_UINT32(ptr) == MKID('DIGI') || READ_UINT32(ptr) == MKID('TALK') || READ_UINT32(ptr) == MKID('HSHD')) { @@ -280,14 +295,9 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { if (READ_UINT32(ptr) == MKID('SBNG')) { ptr += READ_BE_UINT32(ptr + 4); - debug(2, "playSound: Skipped SBNG block"); - } - - if (READ_UINT32(ptr) != MKID('SDAT')) { - warning("playSound: Invalid sound %d", soundID); - return; // abort } + assert(READ_UINT32(ptr) == MKID('SDAT')); size = READ_BE_UINT32(ptr+4) - 8; if (heOffset < 0 || heOffset > size) { warning("playSound: Invalid sound offset (%d) in sound %d", heOffset, soundID); @@ -301,13 +311,15 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { _overrideFreq = 0; } - // TODO: Set sound channel based on heChannel - // Set sound looping based on heFlags + if (heFlags & 1) { + _vm->_mixer->stopHandle(_heSoundChannels[heChannel]); + flags |= SoundMixer::FLAG_LOOP; + } // Allocate a sound buffer, copy the data into it, and play sound = (char *)malloc(size); memcpy(sound, ptr + heOffset + 8, size); - _vm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID); + _vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); } else if (READ_UINT32(ptr) == MKID('MRAW')) { // pcm music in 3DO humongous games @@ -666,26 +678,26 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, SoundHandle *handl } if (_vm->_features & GF_HUMONGOUS) { - int extra = 0; _sfxMode |= mode; // Skip the TALK (8) and HSHD (24) chunks _sfxFile->seek(offset + 32, SEEK_SET); if (_sfxFile->readUint32LE() == TO_LE_32(MKID('SBNG'))) { - debug(2, "startTalkSound: Skipped SBNG block"); // Skip the SBNG, so we end up at the SDAT chunk - extra = _sfxFile->readUint32BE(); - _sfxFile->seek(extra - 4, SEEK_CUR); - size = _sfxFile->readUint32BE() - 8; - } else { - _sfxFile->seek(+4, SEEK_CUR); - size = b - 40; + size = _sfxFile->readUint32BE() - 4; + _sfxFile->seek(size, SEEK_CUR); } - + size = _sfxFile->readUint32BE() - 8; sound = (byte *)malloc(size); _sfxFile->read(sound, size); - _vm->_mixer->playRaw(handle, sound, size, 11000, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); + + if (_vm->_heversion >= 70) { + int channel = _vm->VAR(_vm->VAR_SOUND_CHANNEL); + _vm->_mixer->playRaw(&_heSoundChannels[channel], sound, size, 11000, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE, 1); + } else { + _vm->_mixer->playRaw(handle, sound, size, 11000, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); + } return; } @@ -780,7 +792,9 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, SoundHandle *handl void Sound::stopTalkSound() { if (_sfxMode & 2) { if (_vm->_imuseDigital) { - _vm->_imuseDigital->stopSound(kTalkSoundID); + _vm->_mixer->stopID(kTalkSoundID); + } else if (_vm->_heversion >= 70) { + _vm->_imuseDigital->stopSound(1); } else { _vm->_mixer->stopHandle(_talkChannelHandle); } @@ -806,6 +820,15 @@ bool Sound::isMouthSyncOff(uint pos) { } +int Sound::getSoundElapsedTime(int sound) const { + if (sound >= 10000) { + int channel = sound - 10000; + return _vm->_mixer->getSoundElapsedTime(_heSoundChannels[channel]); + } else { + return _vm->_mixer->getSoundElapsedTimeOfSoundID(sound); + } +} + int Sound::isSoundRunning(int sound) const { if (_vm->_imuseDigital) return (_vm->_imuseDigital->getSoundStatus(sound) != 0); @@ -824,12 +847,9 @@ int Sound::isSoundRunning(int sound) const { else if (_vm->_imuse) return (_vm->_imuse->getSoundStatus(sound)); } else if (sound >= 10000) { - // TODO report sound ID on channel - // channel = sound - 10000 - if (sound == 10000) - return (_vm->_mixer->isSoundIDActive(_currentMusic) ? _currentMusic : 0); - else if (sound == 10001) - return _vm->_mixer->isSoundHandleActive(_talkChannelHandle); + int channel = sound - 10000; + if (_vm->_mixer->isSoundHandleActive(_heSoundChannels[channel])) + return _vm->_mixer->getActiveChannelSoundID(_heSoundChannels[channel]); else return 0; } @@ -915,10 +935,8 @@ void Sound::stopSound(int sound) { else if (_vm->_imuse) _vm->_imuse->stopSound(_vm->_imuse->getSoundStatus(-1)); } else if ( sound >= 10000) { - // TODO: Stop sound channel - // channel = sound - 10000 - if (sound == 10000) - _vm->_mixer->stopID(_currentMusic); + int channel = sound - 10000; + _vm->_mixer->stopHandle(_heSoundChannels[channel]); } } diff --git a/scumm/sound.h b/scumm/sound.h index d86b7c5c45..88bf463d92 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -85,6 +85,7 @@ protected: int16 _currentMusic; public: SoundHandle _talkChannelHandle; // Handle of mixer channel actor is talking on + SoundHandle _heSoundChannels[8]; bool _soundsPaused; byte _sfxMode; @@ -100,6 +101,7 @@ public: void startTalkSound(uint32 offset, uint32 b, int mode, SoundHandle *handle = NULL); void stopTalkSound(); bool isMouthSyncOff(uint pos); + int getSoundElapsedTime(int sound) const; int isSoundRunning(int sound) const; bool isSoundInUse(int sound) const; void stopSound(int sound); diff --git a/scumm/wiz_he.cpp b/scumm/wiz_he.cpp index bb9a803f0e..8e430f9cd0 100644 --- a/scumm/wiz_he.cpp +++ b/scumm/wiz_he.cpp @@ -916,12 +916,13 @@ uint8 *ScummEngine_v72he::drawWizImage(int resNum, int state, int x1, int y1, in cw = width; ch = height; } else { + VirtScreen *pvs = &virtscr[kMainVirtScreen]; if (dstPtr) { cw = READ_LE_UINT32(dstPtr + 0x4); ch = READ_LE_UINT32(dstPtr + 0x8); + assert(cw <= pvs->w && ch <= pvs->h); dst = dstPtr; } else { - VirtScreen *pvs = &virtscr[kMainVirtScreen]; if (flags & kWIFMarkBufferDirty) { dst = pvs->getPixels(0, pvs->topline); } else { diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 1785f937ae..f9f0e32316 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -367,6 +367,14 @@ bool SoundMixer::isSoundIDActive(int id) { return false; } +int SoundMixer::getActiveChannelSoundID(SoundHandle handle) { + Common::StackLock lock(_mutex); + const int index = handle._val % NUM_CHANNELS; + if (_channels[index]) + return _channels[index]->getId(); + return 0; +} + bool SoundMixer::isSoundHandleActive(SoundHandle handle) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; diff --git a/sound/mixer.h b/sound/mixer.h index 48aea32e49..6b888af247 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -205,9 +205,17 @@ public: bool isSoundIDActive(int id); /** + * Get the sound ID of handle sound + * + * @param handle sound to query + * @return sound ID if active + */ + int getActiveChannelSoundID(SoundHandle handle); + + /** * Check if a sound with the given hANDLE is active. * - * @param handle the sound to query + * @param handle sound to query * @return true if the sound is active */ bool isSoundHandleActive(SoundHandle handle); |