[Scummvm-git-logs] scummvm master -> a9da8197392edabfc60bc339df2e6a76415ba0c5
elasota
noreply at scummvm.org
Sat May 20 08:50:36 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:
5b743a2617 VCRUISE: Implement SndHalt opcode
6fd5f839f4 VCRUISE: Resolve all screen names at load time to fix error when leaving first balloon area.
a9da819739 VCRUISE: Consume animation change from animChange when using it. Fixes broken animations when using balloon nav compute
Commit: 5b743a261726c1a7d4f297e7ade9aacc6adfa39b
https://github.com/scummvm/scummvm/commit/5b743a261726c1a7d4f297e7ade9aacc6adfa39b
Author: elasota (ejlasota at gmail.com)
Date: 2023-05-20T04:50:11-04:00
Commit Message:
VCRUISE: Implement SndHalt opcode
Changed paths:
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 40ad47afe86..884dc172538 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -555,7 +555,7 @@ SoundCache::~SoundCache() {
SoundInstance::SoundInstance()
: id(0), rampStartVolume(0), rampEndVolume(0), rampRatePerMSec(0), rampStartTime(0), rampTerminateOnCompletion(false),
- volume(0), balance(0), effectiveBalance(0), effectiveVolume(0), is3D(false), isLooping(false), isSpeech(false), isSilencedLoop(false), x(0), y(0), endTime(0), duration(0) {
+ volume(0), balance(0), effectiveBalance(0), effectiveVolume(0), is3D(false), loopingType(kSoundLoopingTypeNotLooping), isSpeech(false), isSilencedLoop(false), x(0), y(0), startTime(0), endTime(0), duration(0) {
}
SoundInstance::~SoundInstance() {
@@ -993,7 +993,7 @@ Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, const Common::FSNode &roo
_havePendingCompletionCheck(false), _havePendingPlayAmbientSounds(false), _ambientSoundFinishTime(0), _escOn(false), _debugMode(false), _fastAnimationMode(false),
_musicTrack(0), _musicActive(true), _scoreSectionEndTime(0), _musicVolume(getDefaultSoundVolume()), _musicVolumeRampStartTime(0), _musicVolumeRampStartVolume(0), _musicVolumeRampRatePerMSec(0), _musicVolumeRampEnd(0),
_panoramaDirectionFlags(0),
- _loadedAnimation(0), _loadedAnimationHasSound(false), _animPendingDecodeFrame(0), _animDisplayingFrame(0), _animFirstFrame(0), _animLastFrame(0), _animStopFrame(0), _animVolume(getDefaultSoundVolume()),
+ _loadedAnimation(0), _loadedAnimationHasSound(false), _animTerminateAtStartOfFrame(true), _animPendingDecodeFrame(0), _animDisplayingFrame(0), _animFirstFrame(0), _animLastFrame(0), _animStopFrame(0), _animVolume(getDefaultSoundVolume()),
_animStartTime(0), _animFramesDecoded(0), _animDecoderState(kAnimDecoderStateStopped),
_animPlayWhileIdle(false), _idleLockInteractions(false), _idleIsOnInteraction(false), _idleHaveClickInteraction(false), _idleHaveDragInteraction(false), _idleInteractionID(0), _haveIdleStaticAnimation(false),
_inGameMenuState(kInGameMenuStateInvisible), _inGameMenuActiveElement(0), _inGameMenuButtonActive {false, false, false, false, false},
@@ -1791,6 +1791,8 @@ void Runtime::exitGyroIdle() {
}
void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAnimationEnded) {
+ bool terminateAtStartOfFrame = _animTerminateAtStartOfFrame;
+
outAnimationEnded = false;
if (!_animDecoder) {
@@ -1835,6 +1837,11 @@ void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAn
if (!needNewFrame)
break;
+ if (!terminateAtStartOfFrame && !loop && _animPendingDecodeFrame > _animLastFrame) {
+ outAnimationEnded = true;
+ return;
+ }
+
// We check this here for timing reasons: The no-loop case after the draw terminates the animation as soon as the last frame
// starts delaying without waiting for the time until the next frame to expire.
// The loop check here DOES wait for the time until next frame to expire.
@@ -1932,7 +1939,7 @@ void Runtime::continuePlayingAnimation(bool loop, bool useStopFrame, bool &outAn
}
if (!loop) {
- if (_animDisplayingFrame >= _animLastFrame) {
+ if (terminateAtStartOfFrame && _animDisplayingFrame >= _animLastFrame) {
_animDecoder->pauseVideo(true);
_animDecoderState = kAnimDecoderStatePaused;
@@ -3342,6 +3349,7 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
_animLastFrame = animDef.lastFrame;
_animConstraintRect = animDef.constraintRect;
_animFrameRateLock = Fraction();
+ _animTerminateAtStartOfFrame = true;
SfxData::PlaylistMap_t::const_iterator playlistIt = _sfxData.playlists.find(animDef.animName);
@@ -3381,11 +3389,13 @@ void Runtime::setSound3DParameters(SoundInstance &snd, int32 x, int32 y, const S
}
void Runtime::triggerSound(bool looping, SoundInstance &snd, int32 volume, int32 balance, bool is3D, bool isSpeech) {
+ SoundLoopingType oldLoopingType = snd.loopingType;
+
snd.volume = volume;
snd.balance = balance;
snd.is3D = is3D;
- snd.isLooping = looping;
snd.isSpeech = isSpeech;
+ snd.loopingType = (looping ? kSoundLoopingTypeLooping : kSoundLoopingTypeNotLooping);
computeEffectiveVolumeAndBalance(snd);
@@ -3417,8 +3427,9 @@ void Runtime::triggerSound(bool looping, SoundInstance &snd, int32 volume, int32
}
// Construct looping stream if needed and none exists
- if (looping && !cache->loopingStream) {
+ if (looping && !cache->loopingStream || oldLoopingType == kSoundLoopingTypeTerminated) {
cache->player.reset();
+ cache->loopingStream.reset();
cache->loopingStream.reset(new Audio::LoopingAudioStream(cache->stream.get(), 0, DisposeAfterUse::NO, true));
}
@@ -3439,10 +3450,11 @@ void Runtime::triggerSound(bool looping, SoundInstance &snd, int32 volume, int32
cache->player->play(snd.effectiveVolume, snd.effectiveBalance);
}
+ snd.startTime = g_system->getMillis();
if (looping)
snd.endTime = 0;
else
- snd.endTime = g_system->getMillis(true) + static_cast<uint32>(cache->stream->getLength().msecs()) + 1000u;
+ snd.endTime = snd.startTime + snd.duration + 1000u;
}
void Runtime::triggerSoundRamp(SoundInstance &snd, uint durationMSec, int32 newVolume, bool terminateOnCompletion) {
@@ -3452,7 +3464,7 @@ void Runtime::triggerSoundRamp(SoundInstance &snd, uint durationMSec, int32 newV
snd.rampStartTime = g_system->getMillis();
snd.rampRatePerMSec = 65536;
- if (!snd.isLooping && newVolume == getSilentSoundVolume())
+ if (snd.loopingType == kSoundLoopingTypeLooping && newVolume == getSilentSoundVolume())
snd.rampTerminateOnCompletion = true;
if (durationMSec)
@@ -3531,6 +3543,21 @@ void Runtime::stopSound(SoundInstance &sound) {
sound.isSilencedLoop = false;
}
+void Runtime::convertLoopingSoundToNonLooping(SoundInstance &sound) {
+ if (!sound.cache)
+ return;
+
+ if (sound.cache->loopingStream) {
+ sound.cache->loopingStream->setRemainingIterations(1);
+ sound.loopingType = kSoundLoopingTypeTerminated;
+
+ uint32 currentTime = g_system->getMillis();
+
+ uint32 alreadyPlayedTime = ((currentTime - sound.startTime) % sound.duration);
+ sound.endTime = currentTime + sound.duration - alreadyPlayedTime;
+ }
+}
+
void Runtime::updateSounds(uint32 timestamp) {
for (uint sndIndex = 0; sndIndex < _activeSounds.size(); sndIndex++) {
SoundInstance &snd = *_activeSounds[sndIndex];
@@ -3567,7 +3594,7 @@ void Runtime::updateSounds(uint32 timestamp) {
snd.endTime = 0;
}
- if (snd.isLooping) {
+ if (snd.loopingType == kSoundLoopingTypeLooping) {
if (snd.volume <= getSilentSoundVolume()) {
if (!snd.isSilencedLoop) {
if (snd.cache) {
@@ -4928,7 +4955,7 @@ void Runtime::recordSaveGameSnapshot() {
}
saveSound.is3D = sound.is3D;
- saveSound.isLooping = sound.isLooping;
+ saveSound.isLooping = (sound.loopingType == kSoundLoopingTypeLooping);
saveSound.isSpeech = sound.isSpeech;
saveSound.x = sound.x;
saveSound.y = sound.y;
@@ -5034,7 +5061,7 @@ void Runtime::restoreSaveGameSnapshot() {
si->volume = sound.volume;
si->balance = sound.balance;
si->is3D = sound.is3D;
- si->isLooping = sound.isLooping;
+ si->loopingType = (sound.isLooping ? kSoundLoopingTypeLooping : kSoundLoopingTypeNotLooping);
si->isSpeech = sound.isSpeech;
si->x = sound.x;
si->y = sound.y;
@@ -5381,6 +5408,12 @@ void Runtime::scriptOpAnimS(ScriptArg_t arg) {
// Static animations start on the last frame
changeAnimation(animDef, animDef.lastFrame, false);
+ // We use different behavior from the original game to mostly speed up one-frame animations by terminating them
+ // at the start of the last frame instead of the end of the last frame. However, this causes the mechanical
+ // keyboard to play all of the pin animations at once which is kind of annoying.
+ if (_gameID == GID_SCHIZM && animDef.animName.hasPrefix("WEJSCIE_DN"))
+ _animTerminateAtStartOfFrame = false;
+
_gameState = kGameStateWaitingForAnimation;
_screenNumber = stackArgs[kAnimDefStackArgs + 0];
_direction = stackArgs[kAnimDefStackArgs + 1];
@@ -6626,7 +6659,18 @@ void Runtime::scriptOpSndWait(ScriptArg_t arg) {
}
}
-OPCODE_STUB(SndHalt)
+void Runtime::scriptOpSndHalt(ScriptArg_t arg) {
+ TAKE_STACK_INT(1);
+
+ SoundInstance *snd = resolveSoundByID(stackArgs[0]);
+ if (snd) {
+ convertLoopingSoundToNonLooping(*snd);
+
+ _delayCompletionTime = snd->endTime;
+ _gameState = kGameStateDelay;
+ }
+}
+
OPCODE_STUB(SndToBack)
void Runtime::scriptOpSndStop(ScriptArg_t arg) {
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 5dc39cfd4a3..2488b8da2fb 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -43,6 +43,7 @@ namespace Audio {
class AudioStream;
class SeekableAudioStream;
+class LoopingAudioStream;
} // End of namespace Audio
@@ -216,10 +217,16 @@ struct SoundCache {
~SoundCache();
Common::SharedPtr<Audio::SeekableAudioStream> stream;
- Common::SharedPtr<Audio::AudioStream> loopingStream;
+ Common::SharedPtr<Audio::LoopingAudioStream> loopingStream;
Common::SharedPtr<AudioPlayer> player;
};
+enum SoundLoopingType {
+ kSoundLoopingTypeNotLooping, // Was never looping
+ kSoundLoopingTypeTerminated, // Was looping and then converted into non-looping
+ kSoundLoopingTypeLooping, // Is looping
+};
+
struct SoundInstance {
SoundInstance();
~SoundInstance();
@@ -242,7 +249,7 @@ struct SoundInstance {
int32 effectiveBalance;
bool is3D;
- bool isLooping;
+ SoundLoopingType loopingType;
bool isSpeech;
bool isSilencedLoop; // Loop is still playing but reached 0 volume so the player was unloaded
int32 x;
@@ -250,6 +257,7 @@ struct SoundInstance {
SoundParams3D params3D;
+ uint32 startTime;
uint32 endTime;
uint32 duration;
};
@@ -817,6 +825,7 @@ private:
void triggerSound(bool looping, SoundInstance &sound, int32 volume, int32 balance, bool is3D, bool isSpeech);
void triggerSoundRamp(SoundInstance &sound, uint durationMSec, int32 newVolume, bool terminateOnCompletion);
void stopSound(SoundInstance &sound);
+ void convertLoopingSoundToNonLooping(SoundInstance &sound);
void updateSounds(uint32 timestamp);
void updateSubtitles();
void update3DSounds();
@@ -1170,6 +1179,7 @@ private:
Common::SharedPtr<Video::AVIDecoder> _animDecoder;
Common::SharedPtr<SfxPlaylist> _animPlaylist;
AnimDecoderState _animDecoderState;
+ bool _animTerminateAtStartOfFrame;
uint _animPendingDecodeFrame;
uint _animDisplayingFrame;
uint _animFirstFrame;
Commit: 6fd5f839f4dd94ad66915a16a802128693fd5f61
https://github.com/scummvm/scummvm/commit/6fd5f839f4dd94ad66915a16a802128693fd5f61
Author: elasota (ejlasota at gmail.com)
Date: 2023-05-20T04:50:12-04:00
Commit Message:
VCRUISE: Resolve all screen names at load time to fix error when leaving first balloon area.
Changed paths:
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 884dc172538..0f1bac04b4d 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -1218,6 +1218,9 @@ bool Runtime::bootGame(bool newGame) {
// but the frame range for 27 and 28 is supposed to use room 25 (the root of the duplication), not 26.
loadDuplicateRooms();
debug(1, "Duplicated rooms identified OK");
+
+ loadAllSchizmScreenNames();
+ debug(1, "Screen names resolved OK");
} else {
StartConfigDef &startConfig = _startConfigs[kStartConfigInitial];
startConfig.disc = 1;
@@ -2615,6 +2618,46 @@ void Runtime::loadDuplicateRooms() {
}
}
+void Runtime::loadAllSchizmScreenNames() {
+ assert(_gameID == GID_SCHIZM);
+
+ Common::ArchiveMemberList logics;
+ SearchMan.listMatchingMembers(logics, "Log/Room##.log", true);
+
+ Common::Array<uint> roomsToCompile;
+
+ for (const Common::ArchiveMemberPtr &logic : logics) {
+ Common::String name = logic->getName();
+
+ char d10 = name[4];
+ char d1 = name[5];
+
+ uint roomNumber = (d10 - '0') * 10 + (d1 - '0');
+
+ // Rooms 1 and 3 are always compiled. 2 is a cheat room that contains garbage.
+ if (roomNumber > 3)
+ roomsToCompile.push_back(roomNumber);
+ }
+
+ Common::sort(roomsToCompile.begin(), roomsToCompile.end());
+
+ for (uint roomNumber : roomsToCompile) {
+ if (roomNumber >= _roomDuplicationOffsets.size() || _roomDuplicationOffsets[roomNumber] == 0) {
+ uint roomSetToCompile[3] = {1, 3, roomNumber};
+
+ compileSchizmLogicSet(roomSetToCompile, 3);
+
+ for (const RoomScriptSetMap_t::Node &rssNode : _scriptSet->roomScripts) {
+ if (rssNode._key != roomNumber)
+ continue;
+
+ for (const ScreenNameMap_t::Node &snNode : rssNode._value->screenNames)
+ _globalRoomScreenNameToScreenIDs[roomNumber][snNode._key] = snNode._value;
+ }
+ }
+ }
+}
+
Common::SharedPtr<SoundInstance> Runtime::loadWave(const Common::String &soundName, uint soundID, const Common::ArchiveMemberPtr &archiveMemberPtr) {
for (const Common::SharedPtr<SoundInstance> &activeSound : _activeSounds) {
if (activeSound->name == soundName)
@@ -4453,6 +4496,7 @@ Common::SharedPtr<Graphics::Surface> Runtime::loadGraphic(const Common::String &
Common::SharedPtr<Graphics::Surface> surf(new Graphics::Surface());
surf->copyFrom(*bmpDecoder.getSurface());
+ surf.reset(surf->convertTo(Graphics::createPixelFormat<8888>()));
return surf;
}
@@ -6732,15 +6776,21 @@ void Runtime::scriptOpAnimChange(ScriptArg_t arg) {
void Runtime::scriptOpScreenName(ScriptArg_t arg) {
const Common::String &scrName = _scriptSet->strings[arg];
- RoomScriptSet *rss = getRoomScriptSetForCurrentRoom();
- if (!rss)
- error("Couldn't resolve room number to find screen name: '%s'", scrName.c_str());
+ uint roomNumber = _roomNumber;
+ if (roomNumber < _roomDuplicationOffsets.size())
+ roomNumber -= _roomDuplicationOffsets[roomNumber];
+
+ RoomToScreenNameToRoomMap_t::const_iterator roomIt = _globalRoomScreenNameToScreenIDs.find(roomNumber);
+ if (roomIt != _globalRoomScreenNameToScreenIDs.end()) {
+ ScreenNameToRoomMap_t::const_iterator screenIt = roomIt->_value.find(scrName);
- ScreenNameMap_t::const_iterator screenNameIt = rss->screenNames.find(scrName);
- if (screenNameIt == rss->screenNames.end())
- error("Couldn't resolve screen name '%s'", scrName.c_str());
+ if (screenIt != roomIt->_value.end()) {
+ _scriptStack.push_back(StackValue(static_cast<StackInt_t>(screenIt->_value)));
+ return;
+ }
+ }
- _scriptStack.push_back(StackValue(static_cast<StackInt_t>(screenNameIt->_value)));
+ error("Couldn't resolve screen name '%s'", scrName.c_str());
}
void Runtime::scriptOpExtractByte(ScriptArg_t arg) {
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 2488b8da2fb..03267d3b8be 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -547,6 +547,9 @@ struct FontCacheItem {
Common::SharedPtr<Graphics::Font> keepAlive;
};
+typedef Common::HashMap<Common::String, uint> ScreenNameToRoomMap_t;
+typedef Common::HashMap<uint, ScreenNameToRoomMap_t> RoomToScreenNameToRoomMap_t;
+
class Runtime {
public:
friend class RuntimeMenuInterface;
@@ -794,6 +797,7 @@ private:
void loadConfig(const char *cfgPath);
void loadScore();
void loadDuplicateRooms();
+ void loadAllSchizmScreenNames();
Common::SharedPtr<SoundInstance> loadWave(const Common::String &soundName, uint soundID, const Common::ArchiveMemberPtr &archiveMemberPtr);
SoundCache *loadCache(SoundInstance &sound);
void resolveSoundByName(const Common::String &soundName, bool load, StackInt_t &outSoundID, SoundInstance *&outWave);
@@ -1150,6 +1154,7 @@ private:
Common::Array<Common::SharedPtr<RoomDef> > _roomDefs;
Common::Array<uint> _roomDuplicationOffsets;
+ RoomToScreenNameToRoomMap_t _globalRoomScreenNameToScreenIDs;
Common::SharedPtr<ScriptSet> _scriptSet;
Common::Array<CallStackFrame> _scriptCallStack;
Commit: a9da8197392edabfc60bc339df2e6a76415ba0c5
https://github.com/scummvm/scummvm/commit/a9da8197392edabfc60bc339df2e6a76415ba0c5
Author: elasota (ejlasota at gmail.com)
Date: 2023-05-20T04:50:12-04:00
Commit Message:
VCRUISE: Consume animation change from animChange when using it. Fixes broken animations when using balloon nav computer.
Changed paths:
engines/vcruise/runtime.cpp
engines/vcruise/runtime.h
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 0f1bac04b4d..0d24ae68d3b 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -3953,7 +3953,7 @@ AnimationDef Runtime::stackArgsToAnimDef(const StackInt_t *args) const {
return def;
}
-void Runtime::adjustUsingAnimChange(AnimationDef &animDef) const {
+void Runtime::consumeAnimChangeAndAdjustAnim(AnimationDef &animDef) {
if (_scriptEnv.animChangeSet) {
uint origFirstFrame = animDef.firstFrame;
uint origLastFrame = animDef.lastFrame;
@@ -3966,6 +3966,8 @@ void Runtime::adjustUsingAnimChange(AnimationDef &animDef) const {
animDef.firstFrame = newFirstFrame;
animDef.lastFrame = newLastFrame;
+
+ _scriptEnv.animChangeSet = false;
}
}
@@ -5447,7 +5449,7 @@ void Runtime::scriptOpAnimS(ScriptArg_t arg) {
AnimationDef animDef = stackArgsToAnimDef(stackArgs + 0);
- adjustUsingAnimChange(animDef);
+ consumeAnimChangeAndAdjustAnim(animDef);
// Static animations start on the last frame
changeAnimation(animDef, animDef.lastFrame, false);
@@ -5471,7 +5473,7 @@ void Runtime::scriptOpAnim(ScriptArg_t arg) {
AnimationDef animDef = stackArgsToAnimDef(stackArgs + 0);
- adjustUsingAnimChange(animDef);
+ consumeAnimChangeAndAdjustAnim(animDef);
changeAnimation(animDef, animDef.firstFrame, true, _animSpeedDefault);
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 03267d3b8be..743d50f3516 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -845,7 +845,7 @@ private:
void stopSubtitles();
AnimationDef stackArgsToAnimDef(const StackInt_t *args) const;
- void adjustUsingAnimChange(AnimationDef &animDef) const;
+ void consumeAnimChangeAndAdjustAnim(AnimationDef &animDef);
void pushAnimDef(const AnimationDef &animDef);
void activateScript(const Common::SharedPtr<Script> &script, const ScriptEnvironmentVars &envVars);
More information about the Scummvm-git-logs
mailing list