mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
925 lines
27 KiB
C++
925 lines
27 KiB
C++
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "scumm/imuse_digi/dimuse_engine.h"
|
|
|
|
namespace Scumm {
|
|
|
|
#define DIG_STATE_OFFSET 11
|
|
#define DIG_SEQ_OFFSET (DIG_STATE_OFFSET + 65)
|
|
#define COMI_STATE_OFFSET 3
|
|
|
|
int IMuseDigital::scriptParse(int cmd, int a, int b) {
|
|
if (_scriptInitializedFlag || !cmd) {
|
|
switch (cmd) {
|
|
case DIMUSE_C_SCRIPT_INIT:
|
|
if (_scriptInitializedFlag) {
|
|
debug(5, "IMuseDigital::scriptParse(): script module already initialized");
|
|
return -1;
|
|
} else {
|
|
_scriptInitializedFlag = 1;
|
|
return scriptInit();
|
|
}
|
|
case DIMUSE_C_SCRIPT_TERMINATE:
|
|
_scriptInitializedFlag = 0;
|
|
return scriptTerminate();
|
|
case DIMUSE_C_SCRIPT_SAVE:
|
|
case DIMUSE_C_SCRIPT_RESTORE:
|
|
break;
|
|
case DIMUSE_C_SCRIPT_REFRESH:
|
|
scriptRefresh();
|
|
return 0;
|
|
case DIMUSE_C_SCRIPT_SET_STATE:
|
|
scriptSetState(a);
|
|
return 0;
|
|
case DIMUSE_C_SCRIPT_SET_SEQUENCE:
|
|
scriptSetSequence(a);
|
|
return 0;
|
|
case DIMUSE_C_SCRIPT_CUE_POINT:
|
|
scriptSetCuePoint(a);
|
|
return 0;
|
|
case DIMUSE_C_SCRIPT_SET_ATTRIBUTE:
|
|
return scriptSetAttribute(a, b);
|
|
default:
|
|
debug(5, "IMuseDigital::scriptParse(): unrecognized opcode (%d)", cmd);
|
|
return -1;
|
|
}
|
|
} else {
|
|
debug(5, "IMuseDigital::scriptParse(): script module not initialized");
|
|
return -1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int IMuseDigital::scriptInit() {
|
|
_curMusicState = 0;
|
|
_curMusicSeq = 0;
|
|
_nextSeqToPlay = 0;
|
|
_curMusicCue = 0;
|
|
memset(_attributes, 0, sizeof(_attributes));
|
|
return 0;
|
|
}
|
|
|
|
int IMuseDigital::scriptTerminate() {
|
|
diMUSETerminate();
|
|
|
|
_curMusicState = 0;
|
|
_curMusicSeq = 0;
|
|
_nextSeqToPlay = 0;
|
|
_curMusicCue = 0;
|
|
memset(_attributes, 0, sizeof(_attributes));
|
|
return 0;
|
|
}
|
|
|
|
void IMuseDigital::scriptRefresh() {
|
|
int soundId;
|
|
int nextSound;
|
|
|
|
if (_stopSequenceFlag) {
|
|
scriptSetSequence(0);
|
|
_stopSequenceFlag = 0;
|
|
}
|
|
|
|
soundId = 0;
|
|
|
|
while (1) {
|
|
nextSound = diMUSEGetNextSound(soundId);
|
|
soundId = nextSound;
|
|
|
|
if (!nextSound)
|
|
break;
|
|
|
|
if (diMUSEGetParam(nextSound, DIMUSE_P_SND_HAS_STREAM) && diMUSEGetParam(soundId, DIMUSE_P_STREAM_BUFID) == DIMUSE_BUFFER_MUSIC) {
|
|
if (soundId)
|
|
return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_curMusicSeq)
|
|
scriptSetSequence(0);
|
|
|
|
flushTracks();
|
|
}
|
|
|
|
void IMuseDigital::scriptSetState(int soundId) {
|
|
if (_vm->_game.id == GID_DIG && !_isEarlyDiMUSE) {
|
|
setDigMusicState(soundId);
|
|
} else if (_vm->_game.id == GID_CMI) {
|
|
setComiMusicState(soundId);
|
|
} else {
|
|
setFtMusicState(soundId);
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::scriptSetSequence(int soundId) {
|
|
if (_vm->_game.id == GID_DIG && !_isEarlyDiMUSE) {
|
|
setDigMusicSequence(soundId);
|
|
} else if (_vm->_game.id == GID_CMI) {
|
|
setComiMusicSequence(soundId);
|
|
} else {
|
|
setFtMusicSequence(soundId);
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::scriptSetCuePoint(int cueId) {
|
|
if (!_isEarlyDiMUSE)
|
|
return;
|
|
|
|
if (cueId > 3)
|
|
return;
|
|
|
|
debug(5, "IMuseDigital::scriptSetCuePoint(): Cue point sequence: %d", cueId);
|
|
|
|
if (_curMusicSeq && _curMusicCue != cueId) {
|
|
if (cueId == 0)
|
|
playFtMusic(nullptr, 0, 0);
|
|
else {
|
|
int seq = ((_curMusicSeq - 1) * 4) + cueId;
|
|
playFtMusic(_ftSeqMusicTable[seq].audioName, _ftSeqMusicTable[seq].transitionType, _ftSeqMusicTable[seq].volume);
|
|
}
|
|
}
|
|
|
|
_curMusicCue = cueId;
|
|
}
|
|
|
|
int IMuseDigital::scriptSetAttribute(int attrIndex, int attrVal) {
|
|
// FT appears to set a single attribute to 1 at start-up and
|
|
// never use it again, so we currently ignore that behavior
|
|
if (_vm->_game.id == GID_DIG) {
|
|
_attributes[attrIndex] = attrVal;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int IMuseDigital::scriptTriggerCallback(char *marker) {
|
|
if (marker[0] != '_') {
|
|
debug(5, "IMuseDigital::scriptTriggerCallback(): got marker != '_end', callback ignored");
|
|
return -1;
|
|
}
|
|
_stopSequenceFlag = 1;
|
|
return 0;
|
|
}
|
|
|
|
void Scumm::IMuseDigital::setFtMusicState(int stateId) {
|
|
if (stateId > 48)
|
|
return;
|
|
|
|
debug(5, "IMuseDigital::setFtMusicState(): State music: %s, %s", _ftStateMusicTable[stateId].name, _ftStateMusicTable[stateId].audioName);
|
|
|
|
if (_curMusicState == stateId)
|
|
return;
|
|
|
|
if (_curMusicSeq == 0) {
|
|
if (stateId == 0) {
|
|
playFtMusic(nullptr, 0, 0);
|
|
} else {
|
|
playFtMusic(_ftStateMusicTable[stateId].audioName, _ftStateMusicTable[stateId].transitionType, _ftStateMusicTable[stateId].volume);
|
|
}
|
|
}
|
|
|
|
_curMusicState = stateId;
|
|
}
|
|
|
|
void IMuseDigital::setFtMusicSequence(int seqId) {
|
|
if (seqId > 52)
|
|
return;
|
|
|
|
debug(5, "IMuseDigital::setFtMusicSequence(): Sequence music: %s", _ftSeqNames[seqId].name);
|
|
|
|
if (_curMusicSeq != seqId) {
|
|
if (seqId == 0) {
|
|
if (_curMusicState == 0) {
|
|
playFtMusic(nullptr, 0, 0);
|
|
} else {
|
|
playFtMusic(_ftStateMusicTable[_curMusicState].audioName, _ftStateMusicTable[_curMusicState].transitionType, _ftStateMusicTable[_curMusicState].volume);
|
|
}
|
|
} else {
|
|
int seq = (seqId - 1) * 4;
|
|
playFtMusic(_ftSeqMusicTable[seq].audioName, _ftSeqMusicTable[seq].transitionType, _ftSeqMusicTable[seq].volume);
|
|
}
|
|
}
|
|
|
|
_curMusicSeq = seqId;
|
|
_curMusicCue = 0;
|
|
}
|
|
|
|
|
|
void IMuseDigital::setDigMusicState(int stateId) {
|
|
int l, num = -1;
|
|
|
|
for (l = 0; _digStateMusicTable[l].soundId != -1; l++) {
|
|
if ((_digStateMusicTable[l].soundId == stateId)) {
|
|
debug(5, "IMuseDigital::setDigMusicState(): Set music state: %s, %s", _digStateMusicTable[l].name, _digStateMusicTable[l].filename);
|
|
num = l;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (num == -1) {
|
|
for (l = 0; _digStateMusicMap[l].roomId != -1; l++) {
|
|
if ((_digStateMusicMap[l].roomId == stateId)) {
|
|
break;
|
|
}
|
|
}
|
|
num = l;
|
|
|
|
int offset = _attributes[_digStateMusicMap[num].offset];
|
|
if (offset == 0) {
|
|
if (_attributes[_digStateMusicMap[num].attribPos] != 0) {
|
|
num = _digStateMusicMap[num].stateIndex3;
|
|
} else {
|
|
num = _digStateMusicMap[num].stateIndex1;
|
|
}
|
|
} else {
|
|
int stateIndex2 = _digStateMusicMap[num].stateIndex2;
|
|
if (stateIndex2 == 0) {
|
|
num = _digStateMusicMap[num].stateIndex1 + offset;
|
|
} else {
|
|
num = stateIndex2;
|
|
}
|
|
}
|
|
}
|
|
|
|
debug(5, "IMuseDigital::setDigMusicState(): Set music state: %s, %s", _digStateMusicTable[num].name, _digStateMusicTable[num].filename);
|
|
|
|
if (_curMusicState == num)
|
|
return;
|
|
|
|
if (_curMusicSeq == 0) {
|
|
if (num == 0)
|
|
playDigMusic(nullptr, &_digStateMusicTable[0], num, false);
|
|
else
|
|
playDigMusic(_digStateMusicTable[num].name, &_digStateMusicTable[num], num, false);
|
|
}
|
|
|
|
_curMusicState = num;
|
|
}
|
|
|
|
void IMuseDigital::setDigMusicSequence(int seqId) {
|
|
int l, num = -1;
|
|
|
|
if (seqId == 0)
|
|
seqId = 2000;
|
|
|
|
for (l = 0; _digSeqMusicTable[l].soundId != -1; l++) {
|
|
if ((_digSeqMusicTable[l].soundId == seqId)) {
|
|
debug(5, "IMuseDigital::setDigMusicSequence(): Set music sequence: %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].filename);
|
|
num = l;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (num == -1)
|
|
return;
|
|
|
|
if (_curMusicSeq == num)
|
|
return;
|
|
|
|
if (num != 0) {
|
|
if (_curMusicSeq && ((_digSeqMusicTable[_curMusicSeq].transitionType == 4)
|
|
|| (_digSeqMusicTable[_curMusicSeq].transitionType == 6))) {
|
|
_nextSeqToPlay = num;
|
|
return;
|
|
} else {
|
|
playDigMusic(_digSeqMusicTable[num].name, &_digSeqMusicTable[num], 0, true);
|
|
_nextSeqToPlay = 0;
|
|
_attributes[DIG_SEQ_OFFSET + num] = 1;
|
|
}
|
|
} else {
|
|
if (_nextSeqToPlay != 0) {
|
|
playDigMusic(_digSeqMusicTable[_nextSeqToPlay].name, &_digSeqMusicTable[_nextSeqToPlay], 0, true);
|
|
_attributes[DIG_SEQ_OFFSET + _nextSeqToPlay] = 1;
|
|
num = _nextSeqToPlay;
|
|
_nextSeqToPlay = 0;
|
|
} else {
|
|
if (_curMusicState != 0) {
|
|
playDigMusic(_digStateMusicTable[_curMusicState].name, &_digStateMusicTable[_curMusicState], _curMusicState, true);
|
|
} else {
|
|
playDigMusic(nullptr, &_digStateMusicTable[0], _curMusicState, true);
|
|
}
|
|
|
|
num = 0;
|
|
}
|
|
}
|
|
|
|
_curMusicSeq = num;
|
|
}
|
|
|
|
void IMuseDigital::setComiMusicState(int stateId) {
|
|
int l, num = -1;
|
|
|
|
if (stateId == 0)
|
|
stateId = 1000;
|
|
|
|
if ((_vm->_game.features & GF_DEMO) && stateId == 1000)
|
|
stateId = 0;
|
|
|
|
if (!(_vm->_game.features & GF_DEMO)) {
|
|
for (l = 0; _comiStateMusicTable[l].soundId != -1; l++) {
|
|
if ((_comiStateMusicTable[l].soundId == stateId)) {
|
|
debug(5, "IMuseDigital::setComiMusicState(): Set music state: %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].filename);
|
|
num = l;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (num == -1 && !(_vm->_game.features & GF_DEMO))
|
|
return;
|
|
|
|
if (!(_vm->_game.features & GF_DEMO) && _curMusicState == num) {
|
|
return;
|
|
} else if ((_vm->_game.features & GF_DEMO) && _curMusicState == stateId) {
|
|
return;
|
|
}
|
|
|
|
if (_curMusicSeq == 0) {
|
|
if (_vm->_game.features & GF_DEMO) {
|
|
if (_curMusicSeq == 0) {
|
|
if (stateId == 0)
|
|
playComiDemoMusic(nullptr, &_comiDemoStateMusicTable[0], stateId, false);
|
|
else
|
|
playComiDemoMusic(_comiDemoStateMusicTable[stateId].name, &_comiDemoStateMusicTable[stateId], stateId, false);
|
|
}
|
|
} else {
|
|
if (num == 0)
|
|
playComiMusic(nullptr, &_comiStateMusicTable[0], num, false);
|
|
else
|
|
playComiMusic(_comiStateMusicTable[num].name, &_comiStateMusicTable[num], num, false);
|
|
}
|
|
}
|
|
|
|
if (!(_vm->_game.features & GF_DEMO)) {
|
|
_curMusicState = num;
|
|
} else {
|
|
_curMusicState = stateId;
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::setComiMusicSequence(int seqId) {
|
|
int l, num = -1;
|
|
|
|
if (seqId == 0)
|
|
seqId = 2000;
|
|
|
|
for (l = 0; _comiSeqMusicTable[l].soundId != -1; l++) {
|
|
if ((_comiSeqMusicTable[l].soundId == seqId)) {
|
|
debug(5, "IMuseDigital::setComiMusicSequence(): Set music sequence: %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].filename);
|
|
num = l;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (num == -1)
|
|
return;
|
|
|
|
if (_curMusicSeq == num)
|
|
return;
|
|
|
|
if (num != 0) {
|
|
if (_curMusicSeq && ((_comiSeqMusicTable[_curMusicSeq].transitionType == 4)
|
|
|| (_comiSeqMusicTable[_curMusicSeq].transitionType == 6))) {
|
|
_nextSeqToPlay = num;
|
|
return;
|
|
} else {
|
|
playComiMusic(_comiSeqMusicTable[num].name, &_comiSeqMusicTable[num], 0, true);
|
|
_nextSeqToPlay = 0;
|
|
}
|
|
} else {
|
|
if (_nextSeqToPlay != 0) {
|
|
playComiMusic(_comiSeqMusicTable[_nextSeqToPlay].name, &_comiSeqMusicTable[_nextSeqToPlay], 0, true);
|
|
num = _nextSeqToPlay;
|
|
_nextSeqToPlay = 0;
|
|
} else {
|
|
if (_curMusicState != 0) {
|
|
playComiMusic(_comiStateMusicTable[_curMusicState].name, &_comiStateMusicTable[_curMusicState], _curMusicState, true);
|
|
} else {
|
|
playComiMusic(nullptr, &_comiStateMusicTable[0], _curMusicState, true);
|
|
}
|
|
num = 0;
|
|
}
|
|
}
|
|
|
|
_curMusicSeq = num;
|
|
}
|
|
|
|
void IMuseDigital::playFtMusic(const char *songName, int transitionType, int volume) {
|
|
int oldSoundId = 0;
|
|
int soundId;
|
|
|
|
if (!_spooledMusicEnabled)
|
|
return;
|
|
|
|
// Check for any music piece which is played as a SFX (without an associated stream)
|
|
// and fade it out
|
|
for (int i = diMUSEGetNextSound(0); i; i = diMUSEGetNextSound(i)) {
|
|
if (diMUSEGetParam(i, DIMUSE_P_GROUP) == DIMUSE_GROUP_MUSICEFF && !diMUSEGetParam(i, DIMUSE_P_SND_HAS_STREAM))
|
|
diMUSEFadeParam(i, DIMUSE_P_VOLUME, 0, 200);
|
|
}
|
|
|
|
// Now grab the current standard music soundId: it will either be crossfaded by SwitchStream,
|
|
// or faded out
|
|
for (int j = diMUSEGetNextSound(0); j; j = diMUSEGetNextSound(j)) {
|
|
if (diMUSEGetParam(j, DIMUSE_P_GROUP) == DIMUSE_GROUP_MUSICEFF && diMUSEGetParam(j, DIMUSE_P_SND_HAS_STREAM))
|
|
oldSoundId = j;
|
|
}
|
|
|
|
if (songName) {
|
|
switch (transitionType) {
|
|
case 0:
|
|
debug(5, "IMuseDigital::playFtMusic(): NULL transition, ignored");
|
|
return;
|
|
case 1:
|
|
soundId = getSoundIdByName(songName);
|
|
|
|
if (_filesHandler->openSound(soundId))
|
|
return;
|
|
|
|
if (!soundId) {
|
|
debug(5, "IMuseDigital::playFtMusic(): failed to retrieve soundId for sound \"%s\"", songName);
|
|
break;
|
|
}
|
|
|
|
if (diMUSEStartSound(soundId, 126))
|
|
debug(5, "IMuseDigital::playFtMusic(): transition 1, failed to start sound \"%s\"(%d)", songName, soundId);
|
|
|
|
_filesHandler->closeSound(soundId);
|
|
diMUSESetParam(soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetParam(soundId, DIMUSE_P_VOLUME, volume);
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
soundId = getSoundIdByName(songName);
|
|
if (soundId)
|
|
if (_filesHandler->openSound(soundId))
|
|
return;
|
|
|
|
if (soundId) {
|
|
if (oldSoundId) {
|
|
if (oldSoundId != soundId || transitionType == 2) {
|
|
diMUSESwitchStream(oldSoundId, soundId, _ftCrossfadeBuffer, sizeof(_ftCrossfadeBuffer), 0);
|
|
}
|
|
|
|
// WORKAROUND for bug in the original: at the beginning of the game, going in
|
|
// and out of the bar a couple of times breaks and temporarily stops the music
|
|
// Here, we override the fade out, just like the remastered does
|
|
if (oldSoundId == soundId && soundId == 622 && _vm->enhancementEnabled(kEnhAudioChanges)) {
|
|
diMUSEFadeParam(soundId, DIMUSE_P_VOLUME, volume, 200);
|
|
}
|
|
} else if (diMUSEStartStream(soundId, 126, DIMUSE_BUFFER_MUSIC)) {
|
|
debug(5, "IMuseDigital::playFtMusic(): failed to start the stream for \"%s\" (%d)", songName, soundId);
|
|
}
|
|
|
|
_filesHandler->closeSound(soundId);
|
|
diMUSESetParam(soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetParam(soundId, DIMUSE_P_VOLUME, volume);
|
|
} else {
|
|
debug(5, "IMuseDigital::playFtMusic(): failed to retrieve soundId for sound \"%s\" (%d)", songName, soundId);
|
|
}
|
|
break;
|
|
case 4:
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 200);
|
|
return;
|
|
default:
|
|
debug(5, "IMuseDigital::playFtMusic(): bogus transition type, ignored");
|
|
return;
|
|
}
|
|
} else {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 200);
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::playDigMusic(const char *songName, const imuseDigTable *table, int attribPos, bool sequence) {
|
|
int hookId = 0;
|
|
|
|
if (songName != nullptr) {
|
|
if ((_attributes[DIG_SEQ_OFFSET + 38]) && (!_attributes[DIG_SEQ_OFFSET + 41])) {
|
|
if ((attribPos == 43) || (attribPos == 44))
|
|
hookId = 3;
|
|
}
|
|
|
|
if ((_attributes[DIG_SEQ_OFFSET + 46] != 0) && (_attributes[DIG_SEQ_OFFSET + 48] == 0)) {
|
|
if ((attribPos == 38) || (attribPos == 39))
|
|
hookId = 3;
|
|
}
|
|
|
|
if ((_attributes[DIG_SEQ_OFFSET + 53] != 0)) {
|
|
if ((attribPos == 50) || (attribPos == 51))
|
|
hookId = 3;
|
|
}
|
|
|
|
if ((attribPos != 0) && (hookId == 0)) {
|
|
if (table->attribPos != 0)
|
|
attribPos = table->attribPos;
|
|
hookId = _attributes[DIG_STATE_OFFSET + attribPos];
|
|
if (table->hookId != 0) {
|
|
if ((hookId != 0) && (table->hookId > 1)) {
|
|
_attributes[DIG_STATE_OFFSET + attribPos] = 2;
|
|
} else {
|
|
_attributes[DIG_STATE_OFFSET + attribPos] = hookId + 1;
|
|
if (table->hookId < hookId + 1)
|
|
_attributes[DIG_STATE_OFFSET + attribPos] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
// If a sound is found (and its stream is active), fade it out if it's a music track
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_GROUP) == DIMUSE_GROUP_MUSICEFF && !diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM))
|
|
diMUSEFadeParam(nextSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
}
|
|
|
|
int oldSoundId = 0;
|
|
nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM) && (diMUSEGetParam(nextSoundId, DIMUSE_P_STREAM_BUFID) == DIMUSE_BUFFER_MUSIC)) {
|
|
oldSoundId = nextSoundId;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!songName) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
return;
|
|
}
|
|
|
|
switch (table->transitionType) {
|
|
case 0:
|
|
debug(5, "IMuseDigital::playDigMusic(): NULL transition, ignored");
|
|
break;
|
|
case 1:
|
|
if (_filesHandler->openSound(table->soundId))
|
|
return;
|
|
|
|
if (table->soundId) {
|
|
if (diMUSEStartSound(table->soundId, 126))
|
|
debug(5, "IMuseDigital::playDigMusic(): transition 1, failed to start the sound (%d)", table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 1);
|
|
diMUSEFadeParam(table->soundId, DIMUSE_P_VOLUME, 127, 120);
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
} else {
|
|
debug(5, "IMuseDigital::playDigMusic(): transition 1, empty soundId, ignored");
|
|
}
|
|
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
if (_filesHandler->openSound(table->soundId))
|
|
return;
|
|
|
|
if (table->filename[0] == 0 || table->soundId == 0) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 60);
|
|
return;
|
|
}
|
|
|
|
if (table->transitionType == 4) {
|
|
_stopSequenceFlag = 0;
|
|
diMUSESetTrigger(table->soundId, MKTAG('_', 'e', 'n', 'd'), DIMUSE_C_SCRIPT_CALLBACK);
|
|
}
|
|
|
|
if (oldSoundId) {
|
|
if (table->transitionType == 2) {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, 1800, 0, 0);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
diMUSEProcessStreams();
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF); // Repeated intentionally
|
|
return;
|
|
}
|
|
|
|
if (oldSoundId != table->soundId) {
|
|
if ((!sequence) && (table->attribPos != 0) &&
|
|
(table->attribPos == _digStateMusicTable[_curMusicState].attribPos)) {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, 1800, 0, 1);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSEProcessStreams();
|
|
} else {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, 1800, 0, 0);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
diMUSEProcessStreams();
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF); // Repeated intentionally
|
|
}
|
|
}
|
|
} else {
|
|
if (diMUSEStartStream(table->soundId, 126, DIMUSE_BUFFER_MUSIC))
|
|
debug(5, "IMuseDigital::playDigMusic(): failed to start the stream for sound %d", table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
}
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF); // Repeated intentionally
|
|
break;
|
|
case 5:
|
|
debug(5, "IMuseDigital::playDigMusic(): no-op transition type (5), ignored");
|
|
break;
|
|
case 6:
|
|
_stopSequenceFlag = 0;
|
|
diMUSESetTrigger(DIMUSE_SMUSH_SOUNDID + DIMUSE_BUFFER_MUSIC, MKTAG('_', 'e', 'n', 'd'), DIMUSE_C_SCRIPT_CALLBACK);
|
|
break;
|
|
case 7:
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 60);
|
|
break;
|
|
default:
|
|
debug(5, "IMuseDigital::playDigMusic(): bogus transition type, ignored");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::playComiDemoMusic(const char *songName, const imuseComiTable *table, int attribPos, bool sequence) {
|
|
// This is a stripped down version of playDigMusic
|
|
int hookId = 0;
|
|
|
|
if (songName != nullptr) {
|
|
if (attribPos != 0) {
|
|
if (table->attribPos != 0)
|
|
attribPos = table->attribPos;
|
|
}
|
|
}
|
|
|
|
int nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
// If a sound is found (and its stream is active), fade it out if it's a music track
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_GROUP) == DIMUSE_GROUP_MUSICEFF && !diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM))
|
|
diMUSEFadeParam(nextSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
}
|
|
|
|
int oldSoundId = 0;
|
|
nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM) && (diMUSEGetParam(nextSoundId, DIMUSE_P_STREAM_BUFID) == DIMUSE_BUFFER_MUSIC)) {
|
|
oldSoundId = nextSoundId;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!songName) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
return;
|
|
}
|
|
|
|
switch (table->transitionType) {
|
|
case 3:
|
|
if (_filesHandler->openSound(table->soundId))
|
|
return;
|
|
|
|
if (table->filename[0] == 0 || table->soundId == 0) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 60);
|
|
return;
|
|
}
|
|
|
|
if (oldSoundId) {
|
|
if (oldSoundId != table->soundId) {
|
|
if ((!sequence) && (table->attribPos != 0) &&
|
|
(table->attribPos == _comiDemoStateMusicTable[_curMusicState].attribPos)) {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, 1800, 0, 1);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSEProcessStreams();
|
|
} else {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, 1800, 0, 0);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
diMUSEProcessStreams();
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF); // Repeated intentionally
|
|
}
|
|
}
|
|
} else {
|
|
if (diMUSEStartStream(table->soundId, 126, DIMUSE_BUFFER_MUSIC))
|
|
debug(5, "IMuseDigital::playComiDemoMusic(): failed to start the stream for sound %d", table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
}
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF); // Repeated intentionally
|
|
break;
|
|
default:
|
|
debug(5, "IMuseDigital::playComiDemoMusic(): bogus or unused transition type, ignored");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void IMuseDigital::playComiMusic(const char *songName, const imuseComiTable *table, int attribPos, bool sequence) {
|
|
int hookId = 0;
|
|
int fadeDelay = 0;
|
|
|
|
if ((songName != nullptr) && (attribPos != 0)) {
|
|
if (table->attribPos != 0)
|
|
attribPos = table->attribPos;
|
|
hookId = _attributes[COMI_STATE_OFFSET + attribPos];
|
|
|
|
if (table->hookId != 0) {
|
|
if ((hookId != 0) && (table->hookId > 1)) {
|
|
_attributes[COMI_STATE_OFFSET + attribPos] = 2;
|
|
} else {
|
|
_attributes[COMI_STATE_OFFSET + attribPos] = hookId + 1;
|
|
if (table->hookId < hookId + 1)
|
|
_attributes[COMI_STATE_OFFSET + attribPos] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
int nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
// If a sound is found (and its stream is active), fade it out if it's a music track
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_GROUP) == DIMUSE_GROUP_MUSICEFF && !diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM))
|
|
diMUSEFadeParam(nextSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
}
|
|
|
|
int oldSoundId = 0;
|
|
nextSoundId = 0;
|
|
while (1) {
|
|
nextSoundId = diMUSEGetNextSound(nextSoundId);
|
|
if (!nextSoundId)
|
|
break;
|
|
|
|
if (diMUSEGetParam(nextSoundId, DIMUSE_P_SND_HAS_STREAM) && (diMUSEGetParam(nextSoundId, DIMUSE_P_STREAM_BUFID) == DIMUSE_BUFFER_MUSIC)) {
|
|
oldSoundId = nextSoundId;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!songName) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 120);
|
|
return;
|
|
}
|
|
|
|
switch (table->transitionType) {
|
|
case 0:
|
|
debug(5, "IMuseDigital::playComiMusic(): NULL transition, ignored");
|
|
break;
|
|
case 1:
|
|
if (_filesHandler->openSound(table->soundId))
|
|
return;
|
|
|
|
if (table->soundId) {
|
|
if (diMUSEStartSound(table->soundId, 126))
|
|
debug(5, "IMuseDigital::playComiMusic(): transition 1, failed to start the sound (%d)", table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 1);
|
|
diMUSEFadeParam(table->soundId, DIMUSE_P_VOLUME, 127, 120);
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
} else {
|
|
debug(5, "IMuseDigital::playComiMusic(): transition 1, empty soundId, ignored");
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 12:
|
|
if (_filesHandler->openSound(table->soundId))
|
|
return;
|
|
|
|
if (table->filename[0] == 0 || table->soundId == 0) {
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 60);
|
|
break;
|
|
}
|
|
|
|
if (table->transitionType == 4) {
|
|
_stopSequenceFlag = 0;
|
|
diMUSESetTrigger(table->soundId, MKTAG('_', 'e', 'n', 'd'), DIMUSE_C_SCRIPT_CALLBACK);
|
|
}
|
|
|
|
if (oldSoundId) {
|
|
fadeDelay = table->fadeOutDelay;
|
|
if (!fadeDelay)
|
|
fadeDelay = 1000;
|
|
else
|
|
fadeDelay = (fadeDelay * 100) / 6; // Set dimuse_table fade out time to millisecond scale
|
|
|
|
if (table->transitionType == 2) {
|
|
diMUSESwitchStream(oldSoundId, table->soundId, fadeDelay, 0, 0);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, table->hookId);
|
|
diMUSEProcessStreams();
|
|
} else if (oldSoundId != table->soundId) {
|
|
if ((!sequence) && (table->attribPos != 0) &&
|
|
(table->attribPos == _comiStateMusicTable[_curMusicState].attribPos)) {
|
|
|
|
debug(5, "IMuseDigital::playComiMusic(): Starting new sound (%s) with same attribute as old sound (%s)",
|
|
table->name, _comiStateMusicTable[_curMusicState].name);
|
|
|
|
diMUSESwitchStream(oldSoundId, table->soundId, fadeDelay, 0, 1);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSEProcessStreams();
|
|
} else {
|
|
switch (table->transitionType) {
|
|
case 12:
|
|
diMUSESetHook(oldSoundId, table->hookId);
|
|
diMUSESetTrigger(oldSoundId, MKTAG('e', 'x', 'i', 't'), DIMUSE_C_SWITCH_STREAM, oldSoundId, table->soundId, fadeDelay, 1, 0);
|
|
diMUSESetTrigger(oldSoundId, MKTAG('e', 'x', 'i', 't'), DIMUSE_C_SET_PARAM, table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetTrigger(oldSoundId, MKTAG('e', 'x', 'i', 't'), DIMUSE_C_SET_PARAM, table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetTrigger(oldSoundId, MKTAG('e', 'x', 'i', 't'), DIMUSE_C_SET_HOOK, table->soundId, hookId);
|
|
diMUSEProcessStreams();
|
|
break;
|
|
default:
|
|
diMUSESwitchStream(oldSoundId, table->soundId, fadeDelay, 0, 0);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
diMUSEProcessStreams();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (diMUSEStartStream(table->soundId, 126, DIMUSE_BUFFER_MUSIC))
|
|
debug(5, "IMuseDigital::playComiMusic(): failed to start the stream for sound %d", table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_VOLUME, 127);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
diMUSESetHook(table->soundId, hookId);
|
|
}
|
|
_filesHandler->closeSound(table->soundId);
|
|
diMUSESetParam(table->soundId, DIMUSE_P_GROUP, DIMUSE_GROUP_MUSICEFF);
|
|
break;
|
|
case 5:
|
|
debug(5, "IMuseDigital::playComiMusic(): no-op transition type (5), ignored");
|
|
break;
|
|
case 6:
|
|
_stopSequenceFlag = 0;
|
|
diMUSESetTrigger(DIMUSE_SMUSH_SOUNDID + DIMUSE_BUFFER_MUSIC, MKTAG('_', 'e', 'n', 'd'), DIMUSE_C_SCRIPT_CALLBACK);
|
|
break;
|
|
case 7:
|
|
if (oldSoundId)
|
|
diMUSEFadeParam(oldSoundId, DIMUSE_P_VOLUME, 0, 60);
|
|
break;
|
|
case 8:
|
|
if (oldSoundId)
|
|
diMUSESetHook(oldSoundId, table->hookId);
|
|
break;
|
|
case 9:
|
|
if (oldSoundId)
|
|
diMUSESetHook(oldSoundId, table->hookId);
|
|
_stopSequenceFlag = 0;
|
|
diMUSESetTrigger(oldSoundId, MKTAG('_', 'e', 'n', 'd'), DIMUSE_C_SCRIPT_CALLBACK);
|
|
break;
|
|
default:
|
|
debug(5, "IMuseDigital::playComiMusic(): bogus transition type, ignored");
|
|
break;
|
|
}
|
|
}
|
|
|
|
} // End of namespace Scumm
|