SCI: Initial implementation of the fanmade sciAudio library

This is used in the fanmade games "LockerGnome Quest Redux" and
"Betrayed Alliance"
This commit is contained in:
Filippos Karapetis 2014-03-28 02:16:54 +02:00
parent c3003eec85
commit 6a519f7f40
3 changed files with 71 additions and 0 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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();