TSAGE: Added saving/restoring of playing sounds to savegames

This commit is contained in:
Paul Gilbert 2011-06-22 23:40:25 +10:00
parent c4a5fa8506
commit 97137e6b27
5 changed files with 100 additions and 20 deletions

View file

@ -21,11 +21,13 @@
*/ */
#include "common/savefile.h" #include "common/savefile.h"
#include "common/mutex.h"
#include "graphics/palette.h" #include "graphics/palette.h"
#include "graphics/scaler.h" #include "graphics/scaler.h"
#include "graphics/thumbnail.h" #include "graphics/thumbnail.h"
#include "tsage/globals.h" #include "tsage/globals.h"
#include "tsage/saveload.h" #include "tsage/saveload.h"
#include "tsage/sound.h"
#include "tsage/tsage.h" #include "tsage/tsage.h"
namespace tSage { namespace tSage {
@ -105,6 +107,7 @@ void Serializer::validate(int v, Common::Serializer::Version minVersion,
Common::Error Saver::save(int slot, const Common::String &saveName) { Common::Error Saver::save(int slot, const Common::String &saveName) {
assert(!getMacroRestoreFlag()); assert(!getMacroRestoreFlag());
Common::StackLock slock1(_globals->_soundManager._serverDisabledMutex);
// Signal any objects registered for notification // Signal any objects registered for notification
_saveNotifiers.notify(false); _saveNotifiers.notify(false);
@ -149,6 +152,7 @@ Common::Error Saver::save(int slot, const Common::String &saveName) {
Common::Error Saver::restore(int slot) { Common::Error Saver::restore(int slot) {
assert(!getMacroRestoreFlag()); assert(!getMacroRestoreFlag());
Common::StackLock slock1(_globals->_soundManager._serverDisabledMutex);
// Signal any objects registered for notification // Signal any objects registered for notification
_loadNotifiers.notify(false); _loadNotifiers.notify(false);
@ -205,7 +209,7 @@ Common::Error Saver::restore(int slot) {
// Final post-restore notifications // Final post-restore notifications
_macroRestoreFlag = false; _macroRestoreFlag = false;
_loadNotifiers.notify(false); _loadNotifiers.notify(true);
return Common::kNoError; return Common::kNoError;
} }

View file

@ -33,7 +33,7 @@ namespace tSage {
typedef void (*SaveNotifierFn)(bool postFlag); typedef void (*SaveNotifierFn)(bool postFlag);
#define TSAGE_SAVEGAME_VERSION 5 #define TSAGE_SAVEGAME_VERSION 6
class SavedObject; class SavedObject;

View file

@ -235,7 +235,11 @@ void SceneManager::listenerSynchronize(Serializer &s) {
if (s.isLoading()) { if (s.isLoading()) {
changeScene(_sceneNumber); changeScene(_sceneNumber);
checkScene();
if (_nextSceneNumber != -1) {
sceneChange();
_nextSceneNumber = -1;
}
} }
_globals->_sceneManager._scrollerRect.synchronize(s); _globals->_sceneManager._scrollerRect.synchronize(s);

View file

@ -44,7 +44,6 @@ SoundManager::SoundManager() {
_groupsAvail = 0; _groupsAvail = 0;
_newVolume = _masterVol = 127; _newVolume = _masterVol = 127;
_suspendedCount = 0;
_driversDetected = false; _driversDetected = false;
_needToRethink = false; _needToRethink = false;
@ -53,6 +52,8 @@ SoundManager::SoundManager() {
SoundManager::~SoundManager() { SoundManager::~SoundManager() {
if (__sndmgrReady) { if (__sndmgrReady) {
Common::StackLock slock(_serverDisabledMutex);
for (Common::List<Sound *>::iterator i = _soundList.begin(); i != _soundList.end(); ) { for (Common::List<Sound *>::iterator i = _soundList.begin(); i != _soundList.end(); ) {
Sound *s = *i; Sound *s = *i;
++i; ++i;
@ -342,6 +343,18 @@ void SoundManager::_sfSoundServer() {
if (sfManager()._newVolume != sfManager()._masterVol) if (sfManager()._newVolume != sfManager()._masterVol)
_sfSetMasterVol(sfManager()._newVolume); _sfSetMasterVol(sfManager()._newVolume);
// If a time index has been set for any sound, fast forward to it
SynchronizedList<Sound *>::iterator i;
for (i = sfManager()._playList.begin(); i != sfManager()._playList.end(); ++i) {
Sound *s = *i;
if (s->_newTimeIndex != 0) {
s->mute(true);
s->_soSetTimeIndex(s->_newTimeIndex);
s->mute(false);
s->_newTimeIndex = 0;
}
}
// Handle any fading if necessary // Handle any fading if necessary
_sfProcessFading(); _sfProcessFading();
@ -474,7 +487,7 @@ void SoundManager::saveNotifier(bool postFlag) {
} }
void SoundManager::saveNotifierProc(bool postFlag) { void SoundManager::saveNotifierProc(bool postFlag) {
warning("TODO: SoundManager::saveNotifierProc"); // Nothing needs to be done when saving the game
} }
void SoundManager::loadNotifier(bool postFlag) { void SoundManager::loadNotifier(bool postFlag) {
@ -482,12 +495,37 @@ void SoundManager::loadNotifier(bool postFlag) {
} }
void SoundManager::loadNotifierProc(bool postFlag) { void SoundManager::loadNotifierProc(bool postFlag) {
warning("TODO: SoundManager::loadNotifierProc"); if (!postFlag) {
// Stop any currently playing sounds
if (__sndmgrReady) {
Common::StackLock slock(_serverDisabledMutex);
for (Common::List<Sound *>::iterator i = _soundList.begin(); i != _soundList.end(); ) {
Sound *s = *i;
++i;
s->stop();
}
}
} else {
// Savegame is now loaded, so iterate over the sound list to prime any sounds as necessary
for (Common::List<Sound *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
Sound *s = *i;
s->orientAfterRestore();
}
}
} }
void SoundManager::listenerSynchronize(Serializer &s) { void SoundManager::listenerSynchronize(Serializer &s) {
s.validate("SoundManager"); s.validate("SoundManager");
warning("TODO: SoundManager listenerSynchronise"); assert(__sndmgrReady && _driversDetected);
if (s.getVersion() < 6)
return;
Common::StackLock slock(_serverDisabledMutex);
_playList.synchronize(s);
_soundList.synchronize(s);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -1188,7 +1226,7 @@ void SoundManager::_sfUpdateVolume(Sound *sound) {
} }
void SoundManager::_sfDereferenceAll() { void SoundManager::_sfDereferenceAll() {
// Orignal used handles for both the driver list and voiceStructPtrs list. This method then refreshed // Orignal used handles for both the driver list and voiceTypeStructPtrs list. This method then refreshed
// pointer lists based on the handles. Since in ScummVM we're just using pointers directly, this // pointer lists based on the handles. Since in ScummVM we're just using pointers directly, this
// method doesn't need any implementation // method doesn't need any implementation
} }
@ -1379,6 +1417,7 @@ Sound::Sound() {
_fadeCounter = 0; _fadeCounter = 0;
_stopAfterFadeFlag = false; _stopAfterFadeFlag = false;
_timer = 0; _timer = 0;
_newTimeIndex = 0;
_loopTimer = 0; _loopTimer = 0;
_trackInfo._numTracks = 0; _trackInfo._numTracks = 0;
_primed = false; _primed = false;
@ -1411,6 +1450,36 @@ Sound::~Sound() {
stop(); stop();
} }
void Sound::synchronize(Serializer &s) {
if (s.getVersion() < 6)
return;
assert(!_remoteReceiver);
s.syncAsSint16LE(_soundResID);
s.syncAsByte(_primed);
s.syncAsByte(_stoppedAsynchronously);
s.syncAsSint16LE(_group);
s.syncAsSint16LE(_sndResPriority);
s.syncAsSint16LE(_fixedPriority);
s.syncAsSint16LE(_sndResLoop);
s.syncAsSint16LE(_fixedLoop);
s.syncAsSint16LE(_priority);
s.syncAsSint16LE(_volume);
s.syncAsSint16LE(_loop);
s.syncAsSint16LE(_pausedCount);
s.syncAsSint16LE(_mutedCount);
s.syncAsSint16LE(_hold);
s.syncAsSint16LE(_cueValue);
s.syncAsSint16LE(_fadeDest);
s.syncAsSint16LE(_fadeSteps);
s.syncAsUint32LE(_fadeTicks);
s.syncAsUint32LE(_fadeCounter);
s.syncAsByte(_stopAfterFadeFlag);
s.syncAsUint32LE(_timer);
s.syncAsSint16LE(_loopTimer);
}
void Sound::play(int soundNum) { void Sound::play(int soundNum) {
prime(soundNum); prime(soundNum);
_soundManager->addToPlayList(this); _soundManager->addToPlayList(this);
@ -1436,6 +1505,7 @@ void Sound::_prime(int soundResID, bool dontQueue) {
if (_primed) if (_primed)
unPrime(); unPrime();
_soundResID = soundResID;
if (_soundResID != -1) { if (_soundResID != -1) {
// Sound number specified // Sound number specified
_isEmpty = false; _isEmpty = false;
@ -1501,12 +1571,13 @@ void Sound::orientAfterDriverChange() {
_trackInfo._numTracks = 0; _trackInfo._numTracks = 0;
_primed = false; _primed = false;
_prime(_soundResID, true); _prime(_soundResID, true);
setTimeIndex(timeIndex); setTimeIndex(timeIndex);
} }
} }
void Sound::orientAfterRestore() { void Sound::orientAfterRestore() {
if (_isEmpty) { if (!_isEmpty) {
int timeIndex = getTimeIndex(); int timeIndex = getTimeIndex();
_primed = false; _primed = false;
_prime(_soundResID, true); _prime(_soundResID, true);
@ -1585,11 +1656,8 @@ void Sound::fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeF
} }
void Sound::setTimeIndex(uint32 timeIndex) { void Sound::setTimeIndex(uint32 timeIndex) {
if (_primed) { if (_primed)
mute(true); _newTimeIndex = timeIndex;
_soSetTimeIndex(timeIndex);
mute(false);
}
} }
uint32 Sound::getTimeIndex() const { uint32 Sound::getTimeIndex() const {
@ -1665,6 +1733,7 @@ void Sound::_soPrimeSound(bool dontQueue) {
} }
_timer = 0; _timer = 0;
_newTimeIndex = 0;
_loopTimer = 0; _loopTimer = 0;
_soPrimeChannelData(); _soPrimeChannelData();
} }
@ -1685,6 +1754,8 @@ void Sound::_soSetTimeIndex(uint timeIndex) {
_soundManager->_needToRethink = true; _soundManager->_needToRethink = true;
break; break;
} }
--timeIndex;
} }
_soundManager->_soTimeIndexFlag = false; _soundManager->_soTimeIndexFlag = false;

View file

@ -123,7 +123,6 @@ struct VoiceStructEntryType0 {
int _channelNum3; int _channelNum3;
int _priority3; int _priority3;
int _field1A; int _field1A;
int _field1B;
}; };
struct VoiceStructEntryType1 { struct VoiceStructEntryType1 {
@ -166,7 +165,7 @@ private:
public: public:
bool __sndmgrReady; bool __sndmgrReady;
int _ourSndResVersion, _ourDrvResVersion; int _ourSndResVersion, _ourDrvResVersion;
Common::List<Sound *> _playList; SynchronizedList<Sound *> _playList;
Common::List<SoundDriver *> _installedDrivers; Common::List<SoundDriver *> _installedDrivers;
VoiceTypeStruct *_voiceTypeStructPtrs[SOUND_ARR_SIZE]; VoiceTypeStruct *_voiceTypeStructPtrs[SOUND_ARR_SIZE];
uint32 _groupsAvail; uint32 _groupsAvail;
@ -174,9 +173,8 @@ public:
int _newVolume; int _newVolume;
Common::Mutex _serverDisabledMutex; Common::Mutex _serverDisabledMutex;
Common::Mutex _serverSuspendedMutex; Common::Mutex _serverSuspendedMutex;
int _suspendedCount;
bool _driversDetected; bool _driversDetected;
Common::List<Sound *> _soundList; SynchronizedList<Sound *> _soundList;
Common::List<SoundDriverEntry> _availableDrivers; Common::List<SoundDriverEntry> _availableDrivers;
bool _needToRethink; bool _needToRethink;
// Misc flags // Misc flags
@ -255,7 +253,6 @@ class Sound: public EventHandler {
private: private:
void _prime(int soundResID, bool dontQueue); void _prime(int soundResID, bool dontQueue);
void _unPrime(); void _unPrime();
void orientAfterRestore();
public: public:
bool _stoppedAsynchronously; bool _stoppedAsynchronously;
int _soundResID; int _soundResID;
@ -276,7 +273,8 @@ public:
int _fadeTicks; int _fadeTicks;
int _fadeCounter; int _fadeCounter;
bool _stopAfterFadeFlag; bool _stopAfterFadeFlag;
uint _timer; uint32 _timer;
uint32 _newTimeIndex;
int _loopTimer; int _loopTimer;
int _chProgram[SOUND_ARR_SIZE]; int _chProgram[SOUND_ARR_SIZE];
int _chModulation[SOUND_ARR_SIZE]; int _chModulation[SOUND_ARR_SIZE];
@ -306,6 +304,9 @@ public:
Sound(); Sound();
~Sound(); ~Sound();
void synchronize(Serializer &s);
void orientAfterRestore();
void play(int soundResID); void play(int soundResID);
void stop(); void stop();
void prime(int soundResID); void prime(int soundResID);