diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/kfile.cpp | 16 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 53 | ||||
-rw-r--r-- | engines/sci/sound/audio.h | 2 |
3 files changed, 71 insertions, 0 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 29e29722d2..65acdbcdf5 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -37,6 +37,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" +#include "sci/sound/audio.h" #include "sci/console.h" namespace Sci { @@ -494,6 +495,21 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { Common::String str = s->_segMan->getString(argv[1]); debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle); + // Handle sciAudio calls in fanmade games here. sciAudio is an + // external .NET library for playing MP3 files in fanmade games. + // It runs in the background, and obtains sound commands from the + // currently running game via text files (called "conductor files"). + // We skip creating these files, and instead handle the calls + // directly. Since the sciAudio calls are only creating text files, + // this is probably the most straightforward place to handle them. + if (handle == 0xFFFF && str.hasPrefix("(sciAudio")) { + Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin(); + iter--; // sciAudio + iter--; // sciAudio child + g_sci->_audio->handleFanmadeSciAudio(iter->sendp, s->_segMan); + return NULL_REG; + } + #ifdef ENABLE_SCI32 if (handle == VIRTUALFILE_HANDLE) { s->_virtualIndexFile->write(str.c_str(), str.size()); diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 3147fbda09..228abba51e 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -61,6 +61,59 @@ void AudioPlayer::stopAllAudio() { audioCdStop(); } +/** + * Handles the sciAudio calls in fanmade games. + * sciAudio is an external .NET library for playing MP3 files in fanmade games. + * It runs in the background, and obtains sound commands from the + * currently running game via text files (called "conductor files"). + * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0 + */ +void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) { + // TODO: This is a bare bones implementation. Only the play/playx and stop commands + // are handled for now - the other commands haven't been observed in any fanmade game + // yet. All the volume related and fading functionality is currently missing. + + Kernel *kernel = g_sci->getKernel(); + + reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command")); + Common::String command = segMan->getString(commandReg); + + if (command == "play" || command == "playx") { + reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName")); + Common::String fileName = segMan->getString(fileNameReg); + + int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount")); + // When loopCount is -1, we treat it as infinite looping, else no looping is done. + // This is observed by game scripts, which can set loopCount to all sorts of random values. + // Adjust loopCount for ScummVM's LoopingAudioStream semantics + loopCount = (loopCount == -1) ? 0 : 1; + + // Determine sound type + Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType; + if (fileName.hasPrefix("music")) + soundType = Audio::Mixer::kMusicSoundType; + else if (fileName.hasPrefix("speech")) + soundType = Audio::Mixer::kSpeechSoundType; + + Common::File *sciAudio = new Common::File(); + // Replace backwards slashes + for (uint i = 0; i < fileName.size(); i++) { + if (fileName[i] == '\\') + fileName.setChar('/', i); + } + sciAudio->open("sciAudio/" + fileName); + Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES); + + // We only support one audio handle + _mixer->playStream(soundType, &_audioHandle, + Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount)); + } else if (command == "stop") { + _mixer->stopHandle(_audioHandle); + } else { + warning("Unhandled sciAudio command: %s", command.c_str()); + } +} + int AudioPlayer::startAudio(uint16 module, uint32 number) { int sampleLen; Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h index 545d35b2ee..9e65d6e0c8 100644 --- a/engines/sci/sound/audio.h +++ b/engines/sci/sound/audio.h @@ -75,6 +75,8 @@ public: void pauseAudio(); void resumeAudio(); + void handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan); + void setSoundSync(ResourceId id, reg_t syncObjAddr, SegManager *segMan); void doSoundSync(reg_t syncObjAddr, SegManager *segMan); void stopSoundSync(); |