[Scummvm-git-logs] scummvm master -> 3598e4b50c61c053f7c0d0bf1bacc852e51a7488
elasota
noreply at scummvm.org
Thu Mar 9 07:10:47 UTC 2023
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
889bc12ae8 VCRUISE: Move completion checks to script termination.
ca75ba28dc VCRUISE: Fix missing return to idle state after operating a gyro.
3598e4b50c VCRUISE: Add sound playlists.
Commit: 889bc12ae8cb447a8315dccd152d4677103719d5
https://github.com/scummvm/scummvm/commit/889bc12ae8cb447a8315dccd152d4677103719d5
Author: elasota (ejlasota at gmail.com)
Date: 2023-03-09T02:10:00-05:00
Commit Message:
VCRUISE: Move completion checks to script termination.
Changed paths:
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 2e38839469e..0bca982a4b5 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -142,8 +142,8 @@ void Runtime::GyroState::reset() {
Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, const Common::FSNode &rootFSNode, VCruiseGameID gameID)
: _system(system), _mixer(mixer), _roomNumber(1), _screenNumber(0), _direction(0), _havePanAnimations(0), _loadedRoomNumber(0), _activeScreenNumber(0),
- _gameState(kGameStateBoot), _gameID(gameID), _havePendingScreenChange(false), _havePendingReturnToIdleState(false), _scriptNextInstruction(0),
- _escOn(false), _debugMode(false), _panoramaDirectionFlags(0),
+ _gameState(kGameStateBoot), _gameID(gameID), _havePendingScreenChange(false), _havePendingReturnToIdleState(false), _havePendingCompletionCheck(false),
+ _scriptNextInstruction(0), _escOn(false), _debugMode(false), _panoramaDirectionFlags(0),
_loadedAnimation(0), _animPendingDecodeFrame(0), _animDisplayingFrame(0), _animFirstFrame(0), _animLastFrame(0), _animStopFrame(0),
_animFrameRateLock(0), _animStartTime(0), _animFramesDecoded(0), _animDecoderState(kAnimDecoderStateStopped),
_animPlayWhileIdle(false), _idleIsOnInteraction(false), _idleHaveClickInteraction(false), _idleHaveDragInteraction(false), _idleInteractionID(0),
@@ -511,6 +511,7 @@ bool Runtime::runGyroIdle() {
gyro.logState();
gyro.currentState--;
_gameState = kGameStateGyroAnimation;
+ _havePendingCompletionCheck = true;
return true;
} else if (targetState > gyro.currentState) {
AnimationDef animDef = _gyros.posAnim;
@@ -523,6 +524,7 @@ bool Runtime::runGyroIdle() {
gyro.logState();
gyro.currentState++;
_gameState = kGameStateGyroAnimation;
+ _havePendingCompletionCheck = true;
return true;
}
@@ -552,56 +554,11 @@ bool Runtime::runGyroAnimation() {
}
void Runtime::exitGyroIdle() {
- bool succeeded = true;
- for (uint i = 0; i < GyroState::kNumGyros; i++) {
- const Gyro &gyro = _gyros.gyros[i];
- if (gyro.requireState && gyro.currentState != gyro.requiredState) {
- succeeded = false;
- break;
- }
-
- if (gyro.numPreviousStates != gyro.numPreviousStatesRequired) {
- succeeded = false;
- break;
- }
-
- bool prevStatesMatch = true;
- for (uint j = 0; j < gyro.numPreviousStates; j++) {
- if (gyro.previousStates[j] != gyro.requiredPreviousStates[j]) {
- prevStatesMatch = false;
- break;
- }
- }
-
- if (!prevStatesMatch) {
- succeeded = false;
- break;
- }
- }
-
- // Activate the corresponding failure or success interaction if present
- if (_scriptSet) {
- RoomScriptSetMap_t::const_iterator roomScriptIt = _scriptSet->roomScripts.find(_roomNumber);
- if (roomScriptIt != _scriptSet->roomScripts.end()) {
- const ScreenScriptSetMap_t &screenScriptsMap = roomScriptIt->_value->screenScripts;
- ScreenScriptSetMap_t::const_iterator screenScriptIt = screenScriptsMap.find(_screenNumber);
- if (screenScriptIt != screenScriptsMap.end()) {
- const ScreenScriptSet &screenScriptSet = *screenScriptIt->_value;
-
- ScriptMap_t::const_iterator interactionScriptIt = screenScriptSet.interactionScripts.find(succeeded ? _gyros.completeInteraction : _gyros.failureInteraction);
- if (interactionScriptIt != screenScriptSet.interactionScripts.end()) {
- const Common::SharedPtr<Script> &script = interactionScriptIt->_value;
- if (script) {
- activateScript(script, ScriptEnvironmentVars());
- return;
- }
- }
- }
- }
- }
+ _gameState = kGameStateScript;
- _havePendingReturnToIdleState = true;
- _gameState = kGameStateIdle;
+ // In Reah, gyro interactions stop the script.
+ if (_gameID == GID_REAH)
+ terminateScript();
}
void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAnimationEnded) {
@@ -852,10 +809,69 @@ void Runtime::terminateScript() {
if (_gameState == kGameStateScript)
_gameState = kGameStateIdle;
+ if (_havePendingCompletionCheck) {
+ _havePendingCompletionCheck = false;
+
+ if (checkCompletionConditions())
+ return;
+ }
+
if (_havePendingScreenChange)
changeToScreen(_roomNumber, _screenNumber);
}
+bool Runtime::checkCompletionConditions() {
+ bool succeeded = true;
+ for (uint i = 0; i < GyroState::kNumGyros; i++) {
+ const Gyro &gyro = _gyros.gyros[i];
+ if (gyro.requireState && gyro.currentState != gyro.requiredState) {
+ succeeded = false;
+ break;
+ }
+
+ if (gyro.numPreviousStates != gyro.numPreviousStatesRequired) {
+ succeeded = false;
+ break;
+ }
+
+ bool prevStatesMatch = true;
+ for (uint j = 0; j < gyro.numPreviousStates; j++) {
+ if (gyro.previousStates[j] != gyro.requiredPreviousStates[j]) {
+ prevStatesMatch = false;
+ break;
+ }
+ }
+
+ if (!prevStatesMatch) {
+ succeeded = false;
+ break;
+ }
+ }
+
+ // Activate the corresponding failure or success interaction if present
+ if (_scriptSet) {
+ RoomScriptSetMap_t::const_iterator roomScriptIt = _scriptSet->roomScripts.find(_roomNumber);
+ if (roomScriptIt != _scriptSet->roomScripts.end()) {
+ const ScreenScriptSetMap_t &screenScriptsMap = roomScriptIt->_value->screenScripts;
+ ScreenScriptSetMap_t::const_iterator screenScriptIt = screenScriptsMap.find(_screenNumber);
+ if (screenScriptIt != screenScriptsMap.end()) {
+ const ScreenScriptSet &screenScriptSet = *screenScriptIt->_value;
+
+ ScriptMap_t::const_iterator interactionScriptIt = screenScriptSet.interactionScripts.find(succeeded ? _gyros.completeInteraction : _gyros.failureInteraction);
+ if (interactionScriptIt != screenScriptSet.interactionScripts.end()) {
+ const Common::SharedPtr<Script> &script = interactionScriptIt->_value;
+ if (script) {
+ activateScript(script, ScriptEnvironmentVars());
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
void Runtime::startTerminatingHorizontalPan(bool isRight) {
// Figure out what slice this is. The last frame is 1 less than usual.
uint slice = (_animDisplayingFrame - _animFirstFrame) * kNumDirections / (_animLastFrame - _animFirstFrame + 1);
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 3d594cc6bae..7385b84406a 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -285,6 +285,7 @@ private:
void drawSectionToScreen(const RenderSection §ion, const Common::Rect &rect);
void commitSectionToScreen(const RenderSection §ion, const Common::Rect &rect);
void terminateScript();
+ bool checkCompletionConditions();
void startTerminatingHorizontalPan(bool isRight);
@@ -470,6 +471,7 @@ private:
uint _activeScreenNumber;
bool _havePendingScreenChange;
bool _havePendingReturnToIdleState;
+ bool _havePendingCompletionCheck;
GameState _gameState;
bool _escOn;
Commit: ca75ba28dc58d759ba31918ffbfab5735f0a9096
https://github.com/scummvm/scummvm/commit/ca75ba28dc58d759ba31918ffbfab5735f0a9096
Author: elasota (ejlasota at gmail.com)
Date: 2023-03-09T02:10:00-05:00
Commit Message:
VCRUISE: Fix missing return to idle state after operating a gyro.
Changed paths:
engines/vcruise/runtime.cpp
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 0bca982a4b5..6078433395d 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -555,6 +555,7 @@ bool Runtime::runGyroAnimation() {
void Runtime::exitGyroIdle() {
_gameState = kGameStateScript;
+ _havePendingReturnToIdleState = true;
// In Reah, gyro interactions stop the script.
if (_gameID == GID_REAH)
Commit: 3598e4b50c61c053f7c0d0bf1bacc852e51a7488
https://github.com/scummvm/scummvm/commit/3598e4b50c61c053f7c0d0bf1bacc852e51a7488
Author: elasota (ejlasota at gmail.com)
Date: 2023-03-09T02:10:01-05:00
Commit Message:
VCRUISE: Add sound playlists.
Changed paths:
engines/vcruise/audio_player.cpp
engines/vcruise/audio_player.h
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
engines/vcruise/vcruise.cpp
diff --git a/engines/vcruise/audio_player.cpp b/engines/vcruise/audio_player.cpp
index 7b648902a3f..876a1dc019e 100644
--- a/engines/vcruise/audio_player.cpp
+++ b/engines/vcruise/audio_player.cpp
@@ -23,10 +23,8 @@
namespace VCruise {
-AudioPlayer::AudioPlayer(Audio::Mixer *mixer, const Common::SharedPtr<Audio::AudioStream> &baseStream, byte volume, int8 balance)
- : _exhausted(false), _mixer(nullptr), _baseStream(baseStream) {
- _mixer = mixer;
- mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, this, -1, volume, balance, DisposeAfterUse::NO);
+AudioPlayer::AudioPlayer(Audio::Mixer *mixer, const Common::SharedPtr<Audio::AudioStream> &baseStream)
+ : _exhausted(false), _isPlaying(false), _mixer(mixer), _baseStream(baseStream) {
}
AudioPlayer::~AudioPlayer() {
@@ -60,16 +58,22 @@ bool AudioPlayer::endOfData() const {
return _exhausted;
}
-void AudioPlayer::sendToMixer(Audio::Mixer *mixer, byte volume, int8 balance) {
- mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, this, -1, volume, balance, DisposeAfterUse::NO);
+void AudioPlayer::play(byte volume, int8 balance) {
+ if (!_isPlaying) {
+ _isPlaying = true;
+ _exhausted = false;
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, this, -1, volume, balance, DisposeAfterUse::NO);
+ }
+
}
void AudioPlayer::stop() {
- if (_mixer)
+ if (_isPlaying) {
_mixer->stopHandle(_handle);
+ _isPlaying = false;
+ }
_exhausted = true;
- _mixer = nullptr;
}
} // End of namespace VCruise
diff --git a/engines/vcruise/audio_player.h b/engines/vcruise/audio_player.h
index f6597e2d79c..4447bcd1eea 100644
--- a/engines/vcruise/audio_player.h
+++ b/engines/vcruise/audio_player.h
@@ -34,7 +34,7 @@ class CachedAudio;
class AudioPlayer : public Audio::AudioStream {
public:
- AudioPlayer(Audio::Mixer *mixer, const Common::SharedPtr<Audio::AudioStream> &baseStream, byte volume, int8 balance);
+ AudioPlayer(Audio::Mixer *mixer, const Common::SharedPtr<Audio::AudioStream> &baseStream);
~AudioPlayer();
int readBuffer(int16 *buffer, const int numSamples) override;
@@ -42,7 +42,7 @@ public:
int getRate() const override;
bool endOfData() const override;
- void sendToMixer(Audio::Mixer *mixer, byte volume, int8 balance);
+ void play(byte volume, int8 balance);
void stop();
private:
@@ -50,6 +50,7 @@ private:
Audio::SoundHandle _handle;
bool _isLooping;
+ bool _isPlaying;
bool _exhausted;
Audio::Mixer *_mixer;
Common::SharedPtr<Audio::AudioStream> _baseStream;
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 6078433395d..45baac7bcda 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -140,6 +140,147 @@ void Runtime::GyroState::reset() {
isWaitingForAnimation = false;
}
+
+SfxPlaylistEntry::SfxPlaylistEntry() : frame(0), balance(0), volume(0) {
+}
+
+SfxPlaylist::SfxPlaylist() {
+}
+
+SfxData::SfxData() {
+}
+
+void SfxData::reset() {
+ playlists.clear();
+ sounds.clear();
+}
+
+void SfxData::load(Common::SeekableReadStream &stream, Audio::Mixer *mixer) {
+ Common::INIFile iniFile;
+
+ iniFile.allowNonEnglishCharacters();
+ if (!iniFile.loadFromStream(stream))
+ warning("SfxData::load failed to parse INI file");
+
+ const Common::INIFile::Section *samplesSection = nullptr;
+ const Common::INIFile::Section *playlistsSection = nullptr;
+
+ Common::INIFile::SectionList sections = iniFile.getSections(); // Why does this require a copy??
+
+ for (const Common::INIFile::Section §ion : sections) {
+ if (section.name == "samples")
+ samplesSection = §ion;
+ else if (section.name == "playlists")
+ playlistsSection = §ion;
+ }
+
+ if (samplesSection) {
+ for (const Common::INIFile::KeyValue &keyValue : samplesSection->keys) {
+ Common::SharedPtr<SfxSound> sample(new SfxSound());
+
+ // Fix up the path delimiter
+ Common::String sfxPath = keyValue.value;
+ for (char &c : sfxPath) {
+ if (c == '\\')
+ c = '/';
+ }
+
+ sfxPath = Common::String("Sfx/") + sfxPath;
+
+ Common::File f;
+ if (!f.open(sfxPath))
+ warning("SfxData::load: Could not open sample file '%s'", sfxPath.c_str());
+
+ int64 size = f.size();
+ if (size <= 0 || size > 0x1fffffffu) {
+ warning("SfxData::load: File is oversized for some reason");
+ continue;
+ }
+
+ sample->soundData.resize(static_cast<uint>(size));
+ if (f.read(&sample->soundData[0], static_cast<uint32>(size)) != size) {
+ warning("SfxData::load: Couldn't read file");
+ continue;
+ }
+
+ sample->memoryStream.reset(new Common::MemoryReadStream(&sample->soundData[0], static_cast<uint32>(size)));
+ sample->audioStream.reset(Audio::makeWAVStream(sample->memoryStream.get(), DisposeAfterUse::NO));
+ sample->audioPlayer.reset(new AudioPlayer(mixer, sample->audioStream));
+
+ this->sounds[keyValue.key] = sample;
+ }
+ }
+
+ if (playlistsSection) {
+ Common::SharedPtr<SfxPlaylist> playlist;
+
+ for (const Common::INIFile::KeyValue &keyValue : playlistsSection->keys) {
+ const Common::String &key = keyValue.key;
+
+ if (key.size() == 0)
+ continue;
+
+ if (key.size() >= 2 && key.firstChar() == '\"' && key.lastChar() == '\"') {
+ if (!playlist) {
+ warning("Found playlist entry outside of a playlist");
+ continue;
+ }
+
+ Common::String workKey = key.substr(1, key.size() - 2);
+
+ Common::Array<Common::String> tokens;
+ for (;;) {
+ uint32 spaceSpanStart = workKey.find(' ');
+
+ if (spaceSpanStart == Common::String::npos) {
+ tokens.push_back(workKey);
+ break;
+ }
+
+ uint32 spaceSpanEnd = spaceSpanStart;
+
+ while (spaceSpanEnd < workKey.size() && workKey[spaceSpanEnd] == ' ')
+ spaceSpanEnd++;
+
+ tokens.push_back(workKey.substr(0, spaceSpanStart));
+ workKey = workKey.substr(spaceSpanEnd, workKey.size() - spaceSpanEnd);
+ }
+
+ if (tokens.size() != 4) {
+ warning("Found unusual playlist entry: %s", key.c_str());
+ continue;
+ }
+
+ unsigned int frameNum = 0;
+ int balance = 0;
+ unsigned int volume = 0;
+
+ if (!sscanf(tokens[0].c_str(), "%u", &frameNum) || !sscanf(tokens[2].c_str(), "%i", &balance) || !sscanf(tokens[3].c_str(), "%u", &volume)) {
+ warning("Malformed playlist entry: %s", key.c_str());
+ continue;
+ }
+
+ SoundMap_t::const_iterator soundIt = this->sounds.find(tokens[1]);
+ if (soundIt == this->sounds.end()) {
+ warning("Playlist entry referenced non-existent sound: %s", tokens[1].c_str());
+ continue;
+ }
+
+ SfxPlaylistEntry plEntry;
+ plEntry.balance = balance;
+ plEntry.frame = frameNum;
+ plEntry.volume = volume;
+ plEntry.sample = soundIt->_value;
+
+ playlist->entries.push_back(plEntry);
+ } else {
+ playlist.reset(new SfxPlaylist());
+ this->playlists[key] = playlist;
+ }
+ }
+ }
+}
+
Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, const Common::FSNode &rootFSNode, VCruiseGameID gameID)
: _system(system), _mixer(mixer), _roomNumber(1), _screenNumber(0), _direction(0), _havePanAnimations(0), _loadedRoomNumber(0), _activeScreenNumber(0),
_gameState(kGameStateBoot), _gameID(gameID), _havePendingScreenChange(false), _havePendingReturnToIdleState(false), _havePendingCompletionCheck(false),
@@ -638,6 +779,21 @@ void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAn
_animPendingDecodeFrame++;
_animFramesDecoded++;
+ if (_animPlaylist) {
+ uint decodeFrameInPlaylist = _animDisplayingFrame - _animFirstFrame;
+ for (const SfxPlaylistEntry &playlistEntry : _animPlaylist->entries) {
+ if (playlistEntry.frame == decodeFrameInPlaylist) {
+ VCruise::AudioPlayer &audioPlayer = *playlistEntry.sample->audioPlayer;
+
+ audioPlayer.stop();
+ playlistEntry.sample->audioStream->seek(0);
+ audioPlayer.play(playlistEntry.volume, playlistEntry.frame);
+
+ // No break, it's possible for there to be multiple sounds in the same frame
+ }
+ }
+ }
+
Common::Rect copyRect = Common::Rect(0, 0, surface->w, surface->h);
if (!_animConstraintRect.isEmpty())
@@ -1258,7 +1414,8 @@ void Runtime::changeMusicTrack(int track) {
if (Audio::SeekableAudioStream *audioStream = Audio::makeWAVStream(wavFile, DisposeAfterUse::YES)) {
Common::SharedPtr<Audio::AudioStream> loopingStream(Audio::makeLoopingAudioStream(audioStream, 0));
- _musicPlayer.reset(new AudioPlayer(_mixer, loopingStream, 255, 0));
+ _musicPlayer.reset(new AudioPlayer(_mixer, loopingStream));
+ _musicPlayer->play(255, 0);
}
} else {
warning("Music file '%s' is missing", wavFileName.c_str());
@@ -1273,6 +1430,8 @@ void Runtime::changeAnimation(const AnimationDef &animDef, bool consumeFPSOverri
void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bool consumeFPSOverride) {
debug("changeAnimation: %u -> %u Initial %u", animDef.firstFrame, animDef.lastFrame, initialFrame);
+ _animPlaylist.reset();
+
int animFile = animDef.animNum;
if (animFile < 0)
animFile = -animFile;
@@ -1295,6 +1454,14 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
warning("Animation file %i is missing", animFile);
delete aviFile;
}
+
+ Common::String sfxFileName = Common::String::format("Sfx/Anim%04i.sfx", animFile);
+ Common::File sfxFile;
+
+ _sfxData.reset();
+
+ if (sfxFile.open(sfxFileName))
+ _sfxData.load(sfxFile, _mixer);
}
if (_animDecoderState == kAnimDecoderStatePlaying) {
@@ -1311,6 +1478,11 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
_animConstraintRect = animDef.constraintRect;
_animFrameRateLock = 0;
+ SfxData::PlaylistMap_t::const_iterator playlistIt = _sfxData.playlists.find(animDef.animName);
+
+ if (playlistIt != _sfxData.playlists.end())
+ _animPlaylist = playlistIt->_value;
+
if (consumeFPSOverride) {
_animFrameRateLock = _scriptEnv.fpsOverride;
_animFramesDecoded = 0;
@@ -1332,14 +1504,12 @@ AnimationDef Runtime::stackArgsToAnimDef(const StackValue_t *args) const {
def.constraintRect.right = args[5];
def.constraintRect.bottom = args[6];
+ def.animName = _animDefNames[args[7]];
+
return def;
}
void Runtime::pushAnimDef(const AnimationDef &animDef) {
- // Going from Schizm's scripts it looks like this IS pushed on to the stack, but encoded as:
- // Bits 0..11: Last frame
- // Bits 12..23: First frame
- // Bits 24..31: Number
_scriptStack.push_back(animDef.animNum);
_scriptStack.push_back(animDef.firstFrame);
_scriptStack.push_back(animDef.lastFrame);
@@ -1348,6 +1518,17 @@ void Runtime::pushAnimDef(const AnimationDef &animDef) {
_scriptStack.push_back(animDef.constraintRect.top);
_scriptStack.push_back(animDef.constraintRect.right);
_scriptStack.push_back(animDef.constraintRect.bottom);
+
+ uint animNameIndex = 0;
+ Common::HashMap<Common::String, uint>::const_iterator nameIt = _animDefNameToIndex.find(animDef.animName);
+ if (nameIt == _animDefNameToIndex.end()) {
+ animNameIndex = _animDefNames.size();
+ _animDefNameToIndex[animDef.animName] = animNameIndex;
+ _animDefNames.push_back(animDef.animName);
+ } else
+ animNameIndex = nameIt->_value;
+
+ _scriptStack.push_back(animNameIndex);
}
void Runtime::activateScript(const Common::SharedPtr<Script> &script, const ScriptEnvironmentVars &envVars) {
@@ -1382,6 +1563,7 @@ bool Runtime::parseIndexDef(IndexParseType parseType, uint roomNumber, const Com
animDef.animNum = animNum;
animDef.firstFrame = firstFrame;
animDef.lastFrame = lastFrame;
+ animDef.animName = key;
} break;
case kIndexParseTypeRRoom: {
Common::String name;
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 7385b84406a..36e11dbb67a 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -31,12 +31,19 @@ class OSystem;
namespace Common {
+class MemoryReadStream;
class RandomSource;
class ReadStream;
class WriteStream;
} // End of namespace Commom
+namespace Audio {
+
+class SeekableAudioStream;
+
+} // End of namespace Audio
+
namespace Graphics {
struct PixelFormat;
@@ -83,6 +90,8 @@ struct AnimationDef {
uint lastFrame; // Inclusive
Common::Rect constraintRect;
+
+ Common::String animName;
};
struct RoomDef {
@@ -126,6 +135,40 @@ struct ScriptEnvironmentVars {
uint fpsOverride;
};
+struct SfxSound {
+ Common::Array<byte> soundData;
+ Common::SharedPtr<Common::MemoryReadStream> memoryStream;
+ Common::SharedPtr<Audio::SeekableAudioStream> audioStream;
+ Common::SharedPtr<AudioPlayer> audioPlayer;
+};
+
+struct SfxPlaylistEntry {
+ SfxPlaylistEntry();
+
+ uint frame;
+ Common::SharedPtr<SfxSound> sample;
+ int8 balance;
+ uint8 volume;
+};
+
+struct SfxPlaylist {
+ SfxPlaylist();
+
+ Common::Array<SfxPlaylistEntry> entries;
+};
+
+struct SfxData {
+ SfxData();
+
+ void reset();
+ void load(Common::SeekableReadStream &stream, Audio::Mixer *mixer);
+
+ typedef Common::HashMap<Common::String, Common::SharedPtr<SfxPlaylist> > PlaylistMap_t;
+ typedef Common::HashMap<Common::String, Common::SharedPtr<SfxSound> > SoundMap_t;
+ PlaylistMap_t playlists;
+ SoundMap_t sounds;
+};
+
class Runtime {
public:
Runtime(OSystem *system, Audio::Mixer *mixer, const Common::FSNode &rootFSNode, VCruiseGameID gameID);
@@ -490,8 +533,10 @@ private:
Common::SharedPtr<Common::RandomSource> _rng;
Common::SharedPtr<AudioPlayer> _musicPlayer;
+ SfxData _sfxData;
Common::SharedPtr<Video::AVIDecoder> _animDecoder;
+ Common::SharedPtr<SfxPlaylist> _animPlaylist;
AnimDecoderState _animDecoderState;
uint _animPendingDecodeFrame;
uint _animDisplayingFrame;
@@ -505,6 +550,9 @@ private:
uint _loadedAnimation;
bool _animPlayWhileIdle;
+ Common::Array<Common::String> _animDefNames;
+ Common::HashMap<Common::String, uint> _animDefNameToIndex;
+
bool _idleIsOnInteraction;
bool _idleHaveClickInteraction;
bool _idleHaveDragInteraction;
@@ -535,7 +583,7 @@ private:
Common::Array<OSEvent> _pendingEvents;
- static const uint kAnimDefStackArgs = 7;
+ static const uint kAnimDefStackArgs = 8;
static const uint kCursorArrow = 0;
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index b2bfb51d325..a1154b42187 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -38,7 +38,7 @@ namespace VCruise {
VCruiseEngine::VCruiseEngine(OSystem *syst, const VCruiseGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
const Common::FSNode gameDataDir(ConfMan.get("path"));
- SearchMan.addDirectory(gameDataDir.getPath(), gameDataDir, 0, 2);
+ SearchMan.addDirectory(gameDataDir.getPath(), gameDataDir, 0, 3);
}
VCruiseEngine::~VCruiseEngine() {
More information about the Scummvm-git-logs
mailing list