void SoundCommandParser::processDisposeSound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } processStopSound(obj, false); _music->soundKill(musicSlot); writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); if (_soundVersion >= SCI_VERSION_1_EARLY) writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); else writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); }
void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } if (musicSlot->isSample) { #ifdef ENABLE_SCI32 if (_soundVersion >= SCI_VERSION_2_1_EARLY) { const int position = g_sci->_audio32->getPosition(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj); if (position == -1) { processStopSound(musicSlot->soundObj, true); } return; } #endif // Update digital sound effect slots uint currentLoopCounter = 0; if (musicSlot->pLoopStream) currentLoopCounter = musicSlot->pLoopStream->getCompleteIterations(); if (currentLoopCounter != musicSlot->sampleLoopCounter) { // during last time we looped at least one time, update loop accordingly musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter; musicSlot->sampleLoopCounter = currentLoopCounter; } if (musicSlot->status == kSoundPlaying) { if (!_music->soundIsActive(musicSlot)) { processStopSound(obj, true); } else { _music->updateAudioStreamTicker(musicSlot); } } else if (musicSlot->status == kSoundPaused) { _music->updateAudioStreamTicker(musicSlot); } // We get a flag from MusicEntry::doFade() here to set volume for the stream if (musicSlot->fadeSetVolume) { _music->soundSetSampleVolume(musicSlot, musicSlot->volume); musicSlot->fadeSetVolume = false; } } else if (musicSlot->pMidiParser) { // Update MIDI slots if (musicSlot->signal == 0) { if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) { if (SELECTOR(dataInc) > -1) writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc); writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127); } } else { // Sync the signal of the sound object writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal); // We need to do this especially because state selector needs to get updated if (musicSlot->signal == SIGNAL_OFFSET) processStopSound(obj, false); } } else { // The sound slot has no data for the currently selected sound card. // An example can be found during the mud wrestling scene in LSL5, room // 730: sound 744 (a splat sound heard when Lana Luscious jumps in the // mud) only contains MIDI channel data. If a non-MIDI sound card is // selected (like Adlib), then the scene freezes. We also need to stop // the sound at this point, otherwise KQ6 Mac breaks because the rest // of the object needs to be reset to avoid a continuous stream of // sound cues. processStopSound(obj, true); // this also sets the signal selector } if (musicSlot->fadeCompleted) { musicSlot->fadeCompleted = false; // We need signal for sci0 at least in iceman as well (room 14, // fireworks). // It is also needed in other games, e.g. LSL6 when talking to the // receptionist (bug #3192166). // TODO: More thorougly check the different SCI version: // * SCI1late sets signal to 0xFE here. (With signal 0xFF // duplicate music plays in LauraBow2CD - bug #6462) // SCI1middle LSL1 1.000.510 does not have the 0xFE; // SCI1late CastleDrBrain demo 1.000.005 does have the 0xFE. // * Other SCI1 games seem to rely on processStopSound to set the signal // * Need to check SCI0 behaviour. uint16 sig; if (getSciVersion() >= SCI_VERSION_1_LATE) sig = 0xFFFE; else sig = SIGNAL_OFFSET; writeSelectorValue(_segMan, obj, SELECTOR(signal), sig); if (_soundVersion <= SCI_VERSION_0_LATE) { processStopSound(obj, false); } else { if (musicSlot->stopAfterFading) processStopSound(obj, false); } } // Sync loop selector for SCI0 if (_soundVersion <= SCI_VERSION_0_LATE) writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); musicSlot->signal = 0; if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker % 60 / 2); } }
reg_t SoundCommandParser::kDoSoundStop(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelSound, "kDoSound(stop): %04x:%04x", PRINT_REG(argv[0])); processStopSound(argv[0], false); return s->r_acc; }
void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } if (musicSlot->pStreamAud) { // Update digital sound effect slots uint currentLoopCounter = 0; if (musicSlot->pLoopStream) currentLoopCounter = musicSlot->pLoopStream->getCompleteIterations(); if (currentLoopCounter != musicSlot->sampleLoopCounter) { // during last time we looped at least one time, update loop accordingly musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter; musicSlot->sampleLoopCounter = currentLoopCounter; } if (musicSlot->status == kSoundPlaying) { if (!_music->soundIsActive(musicSlot)) { processStopSound(obj, true); } else { _music->updateAudioStreamTicker(musicSlot); } } else if (musicSlot->status == kSoundPaused) { _music->updateAudioStreamTicker(musicSlot); } // We get a flag from MusicEntry::doFade() here to set volume for the stream if (musicSlot->fadeSetVolume) { _music->soundSetSampleVolume(musicSlot, musicSlot->volume); musicSlot->fadeSetVolume = false; } } else if (musicSlot->pMidiParser) { // Update MIDI slots if (musicSlot->signal == 0) { if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) { if (SELECTOR(dataInc) > -1) writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc); writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127); } } else { // Sync the signal of the sound object writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal); // We need to do this especially because state selector needs to get updated if (musicSlot->signal == SIGNAL_OFFSET) processStopSound(obj, false); } } else { // Slot actually has no data (which would mean that a sound-resource w/ // unsupported data is used. // (example lsl5 - sound resource 744 - it's roland exclusive writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); // If we don't set signal here, at least the switch to the mud wrestling // room in lsl5 will not work. } if (musicSlot->fadeCompleted) { musicSlot->fadeCompleted = false; // We need signal for sci0 at least in iceman as well (room 14, // fireworks). // It is also needed in other games, e.g. LSL6 when talking to the // receptionist (bug #3192166). if (g_sci->getGameId() == GID_LONGBOW && g_sci->getEngineState()->currentRoomNumber() == 95) { // HACK: Don't set a signal here in the intro of Longbow, as that makes some dialog // boxes disappear too soon (bug #3044844). } else { writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); } if (_soundVersion <= SCI_VERSION_0_LATE) { processStopSound(obj, false); } else { if (musicSlot->stopAfterFading) processStopSound(obj, false); } } // Sync loop selector for SCI0 if (_soundVersion <= SCI_VERSION_0_LATE) writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); musicSlot->signal = 0; if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); } }
reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) { debugC(kDebugLevelSound, "kDoSound(stop): %04x:%04x", PRINT_REG(argv[0])); processStopSound(argv[0], false); return acc; }
void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } if (musicSlot->pStreamAud) { // Update digital sound effect slots uint currentLoopCounter = 0; if (musicSlot->pLoopStream) currentLoopCounter = musicSlot->pLoopStream->getCompleteIterations(); if (currentLoopCounter != musicSlot->sampleLoopCounter) { // during last time we looped at least one time, update loop accordingly musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter; musicSlot->sampleLoopCounter = currentLoopCounter; } if (musicSlot->status == kSoundPlaying) { if (!_music->soundIsActive(musicSlot)) { processStopSound(obj, true); } else { _music->updateAudioStreamTicker(musicSlot); } } else if (musicSlot->status == kSoundPaused) { _music->updateAudioStreamTicker(musicSlot); } // We get a flag from MusicEntry::doFade() here to set volume for the stream if (musicSlot->fadeSetVolume) { _music->soundSetSampleVolume(musicSlot, musicSlot->volume); musicSlot->fadeSetVolume = false; } } else if (musicSlot->pMidiParser) { // Update MIDI slots if (musicSlot->signal == 0) { if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) { if (SELECTOR(dataInc) > -1) writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc); writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127); } } else { // Sync the signal of the sound object writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal); // We need to do this especially because state selector needs to get updated if (musicSlot->signal == SIGNAL_OFFSET) processStopSound(obj, false); } } else { // The sound slot has no data for the currently selected sound card. // An example can be found during the mud wrestling scene in LSL5, room // 730: sound 744 (a splat sound heard when Lana Luscious jumps in the // mud) only contains MIDI channel data. If a non-MIDI sound card is // selected (like Adlib), then the scene freezes. We also need to stop // the sound at this point, otherwise KQ6 Mac breaks because the rest // of the object needs to be reset to avoid a continuous stream of // sound cues. processStopSound(obj, true); // this also sets the signal selector } if (musicSlot->fadeCompleted) { musicSlot->fadeCompleted = false; // We need signal for sci0 at least in iceman as well (room 14, // fireworks). // It is also needed in other games, e.g. LSL6 when talking to the // receptionist (bug #3192166). // CHECKME: At least kq5cd/win and kq6 set signal to 0xFE here, but // kq5cd/dos does not set signal at all. Needs more investigation. writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); if (_soundVersion <= SCI_VERSION_0_LATE) { processStopSound(obj, false); } else { if (musicSlot->stopAfterFading) processStopSound(obj, false); } } // Sync loop selector for SCI0 if (_soundVersion <= SCI_VERSION_0_LATE) writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); musicSlot->signal = 0; if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelectorValue(_segMan, obj, SELECTOR(min), musicSlot->ticker / 3600); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); } }