mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-30 21:00:39 +00:00
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:
parent
c3003eec85
commit
6a519f7f40
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user