aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2011-06-28 22:55:14 +0300
committerEugene Sandulenko2011-06-29 17:16:25 +0300
commit15a16e556ca03b51b1fc03f135834bf57f592b52 (patch)
tree33b1fab3325c2ed4b7cc55e559526a2d08b9672a
parentc32a3ea0d30336771bab460ecccb58c4614e6294 (diff)
downloadscummvm-rg350-15a16e556ca03b51b1fc03f135834bf57f592b52.tar.gz
scummvm-rg350-15a16e556ca03b51b1fc03f135834bf57f592b52.tar.bz2
scummvm-rg350-15a16e556ca03b51b1fc03f135834bf57f592b52.zip
SWORD25: Implement persistence functions for soundengine
Now sound is properly saved/restored. Implemented savegame versioning. Compatibility with old saves pertained.
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp5
-rw-r--r--engines/sword25/kernel/inputpersistenceblock.cpp5
-rw-r--r--engines/sword25/kernel/inputpersistenceblock.h6
-rw-r--r--engines/sword25/kernel/persistenceservice.cpp30
-rw-r--r--engines/sword25/kernel/persistenceservice.h1
-rw-r--r--engines/sword25/sfx/soundengine.cpp75
-rw-r--r--engines/sword25/sfx/soundengine.h11
7 files changed, 115 insertions, 18 deletions
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index f5f33d8e02..3b29b0333f 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -72,7 +72,10 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz
// Seek to the actual PNG image
loadString(*file); // Marker (BS25SAVEGAME)
- loadString(*file); // Version
+ Common::String storedVersionID = loadString(*file); // Version
+ if (storedVersionID != "SCUMMVM1")
+ loadString(*file);
+
loadString(*file); // Description
uint32 compressedGamedataSize = atoi(loadString(*file).c_str());
loadString(*file); // Uncompressed game data size
diff --git a/engines/sword25/kernel/inputpersistenceblock.cpp b/engines/sword25/kernel/inputpersistenceblock.cpp
index c1cd771e39..2d45dfb640 100644
--- a/engines/sword25/kernel/inputpersistenceblock.cpp
+++ b/engines/sword25/kernel/inputpersistenceblock.cpp
@@ -35,9 +35,10 @@
namespace Sword25 {
-InputPersistenceBlock::InputPersistenceBlock(const void *data, uint dataLength) :
+InputPersistenceBlock::InputPersistenceBlock(const void *data, uint dataLength, int version) :
_data(static_cast<const byte *>(data), dataLength),
- _errorState(NONE) {
+ _errorState(NONE),
+ _version(version) {
_iter = _data.begin();
}
diff --git a/engines/sword25/kernel/inputpersistenceblock.h b/engines/sword25/kernel/inputpersistenceblock.h
index f643b06bc1..7e68137246 100644
--- a/engines/sword25/kernel/inputpersistenceblock.h
+++ b/engines/sword25/kernel/inputpersistenceblock.h
@@ -46,7 +46,7 @@ public:
OUT_OF_SYNC
};
- InputPersistenceBlock(const void *data, uint dataLength);
+ InputPersistenceBlock(const void *data, uint dataLength, int version);
virtual ~InputPersistenceBlock();
void read(int16 &value);
@@ -64,6 +64,8 @@ public:
return _errorState;
}
+ int getVersion() const { return _version; }
+
private:
bool checkMarker(byte marker);
bool checkBlockSize(int size);
@@ -72,6 +74,8 @@ private:
Common::Array<byte> _data;
Common::Array<byte>::const_iterator _iter;
ErrorState _errorState;
+
+ int _version;
};
} // End of namespace Sword25
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index c88360e031..27d669caa1 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -50,7 +50,9 @@ static const char *SAVEGAME_DIRECTORY = "saves";
static const char *FILE_MARKER = "BS25SAVEGAME";
static const uint SLOT_COUNT = 18;
static const uint FILE_COPY_BUFFER_SIZE = 1024 * 10;
-static const char *VERSIONID = "SCUMMVM1";
+static const char *VERSIONIDOLD = "SCUMMVM1";
+static const char *VERSIONID = "SCUMMVM2";
+static const int VERSIONNUM = 2;
#define MAX_SAVEGAME_SIZE 100
@@ -99,6 +101,7 @@ struct SavegameInformation {
bool isOccupied;
bool isCompatible;
Common::String description;
+ int version;
uint gamedataLength;
uint gamedataOffset;
uint gamedataUncompressedLength;
@@ -147,9 +150,15 @@ struct PersistenceService::Impl {
// Read in the header
Common::String storedMarker = loadString(file);
Common::String storedVersionID = loadString(file);
+ if (storedVersionID == VERSIONIDOLD) {
+ curSavegameInfo.version = 1;
+ } else {
+ Common::String versionNum = loadString(file);
+ curSavegameInfo.version = atoi(versionNum.c_str());
+ }
Common::String gameDescription = loadString(file);
- Common::String gameDataLength = loadString(file);
- curSavegameInfo.gamedataLength = atoi(gameDataLength.c_str());
+ Common::String gamedataLength = loadString(file);
+ curSavegameInfo.gamedataLength = atoi(gamedataLength.c_str());
Common::String gamedataUncompressedLength = loadString(file);
curSavegameInfo.gamedataUncompressedLength = atoi(gamedataUncompressedLength.c_str());
@@ -158,7 +167,7 @@ struct PersistenceService::Impl {
// The slot is marked as occupied.
curSavegameInfo.isOccupied = true;
// Check if the saved game is compatible with the current engine version.
- curSavegameInfo.isCompatible = (storedVersionID == Common::String(VERSIONID));
+ curSavegameInfo.isCompatible = (curSavegameInfo.version <= VERSIONNUM);
// Load the save game description.
curSavegameInfo.description = gameDescription;
// The offset to the stored save game data within the file.
@@ -242,6 +251,12 @@ Common::String &PersistenceService::getSavegameFilename(uint slotID) {
return result;
}
+int PersistenceService::getSavegameVersion(uint slotID) {
+ if (!checkslotID(slotID))
+ return -1;
+ return _impl->_savegameInformations[slotID].version;
+}
+
bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotFilename) {
// FIXME: This code is a hack which bypasses the savefile API,
// and should eventually be removed.
@@ -264,6 +279,11 @@ bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotF
file->writeString(VERSIONID);
file->writeByte(0);
+ char buf[20];
+ snprintf(buf, 20, "%d", VERSIONNUM);
+ file->writeString(buf);
+ file->writeByte(0);
+
TimeDate dt;
g_system->getTimeAndDate(dt);
file->writeString(formatTimestamp(dt));
@@ -385,7 +405,7 @@ bool PersistenceService::loadGame(uint slotID) {
memcpy(uncompressedDataBuffer, compressedDataBuffer, uncompressedBufferSize);
}
- InputPersistenceBlock reader(&uncompressedDataBuffer[0], curSavegameInfo.gamedataUncompressedLength);
+ InputPersistenceBlock reader(&uncompressedDataBuffer[0], curSavegameInfo.gamedataUncompressedLength, curSavegameInfo.version);
// Einzelne Engine-Module depersistieren.
bool success = true;
diff --git a/engines/sword25/kernel/persistenceservice.h b/engines/sword25/kernel/persistenceservice.h
index f73962892c..59e0a3661d 100644
--- a/engines/sword25/kernel/persistenceservice.h
+++ b/engines/sword25/kernel/persistenceservice.h
@@ -57,6 +57,7 @@ public:
void reloadSlots();
bool isSlotOccupied(uint slotID);
bool isSavegameCompatible(uint slotID);
+ int getSavegameVersion(uint slotID);
Common::String &getSavegameDescription(uint slotID);
Common::String &getSavegameFilename(uint slotID);
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 7c8a6593aa..1b424dac65 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -33,6 +33,8 @@
#include "sword25/sfx/soundengine.h"
#include "sword25/package/packagemanager.h"
#include "sword25/kernel/resource.h"
+#include "sword25/kernel/inputpersistenceblock.h"
+#include "sword25/kernel/outputpersistenceblock.h"
#include "audio/decoders/vorbis.h"
@@ -202,17 +204,29 @@ bool SoundEngine::playSound(const Common::String &fileName, SOUND_TYPES type, fl
return true;
}
-uint SoundEngine::playSoundEx(const Common::String &fileName, SOUND_TYPES type, float volume, float pan, bool loop, int loopStart, int loopEnd, uint layer) {
+uint SoundEngine::playSoundEx(const Common::String &fileName, SOUND_TYPES type, float volume, float pan, bool loop, int loopStart, int loopEnd, uint layer, uint handleId) {
Common::SeekableReadStream *in = Kernel::getInstance()->getPackage()->getStream(fileName);
#ifdef USE_VORBIS
Audio::SeekableAudioStream *stream = Audio::makeVorbisStream(in, DisposeAfterUse::YES);
#endif
uint id;
- SndHandle *handle = getHandle(&id);
+ SndHandle *handle;
- debugC(1, kDebugSound, "SoundEngine::playSoundEx(%s, %d, %f, %f, %d, %d, %d, %d)", fileName.c_str(), type, volume, pan, loop, loopStart, loopEnd, layer);
+ if (handleId == 0x1337)
+ handle = getHandle(&id);
+ else
+ handle = &_handles[handleId];
- handle->type = kAllocatedHandle;
+ handle->fileName = fileName;
+ handle->sndType = type;
+ handle->volume = volume;
+ handle->pan = pan;
+ handle->loop = loop;
+ handle->loopStart = loopStart;
+ handle->loopEnd = loopEnd;
+ handle->layer = layer;
+
+ debugC(1, kDebugSound, "SoundEngine::playSoundEx(%s, %d, %f, %f, %d, %d, %d, %d)", fileName.c_str(), type, volume, pan, loop, loopStart, loopEnd, layer);
#ifdef USE_VORBIS
_mixer->playStream(getType(type), &(handle->handle), stream, -1, (byte)(volume * 255), (int8)(pan * 127));
@@ -311,16 +325,61 @@ bool SoundEngine::canLoadResource(const Common::String &fileName) {
}
-bool SoundEngine::persist(OutputPersistenceBlock &writer) {
- warning("STUB: SoundEngine::persist()");
+ bool SoundEngine::persist(OutputPersistenceBlock &writer) {
+ writer.write(_maxHandleId);
+
+ for (uint i = 0; i < SOUND_HANDLES; i++) {
+ writer.write(_handles[i].id);
+
+ writer.writeString(_handles[i].fileName);
+ writer.write((int)_handles[i].sndType);
+ writer.write(_handles[i].volume);
+ writer.write(_handles[i].pan);
+ writer.write(_handles[i].loop);
+ writer.write(_handles[i].loopStart);
+ writer.write(_handles[i].loopEnd);
+ writer.write(_handles[i].layer);
+ }
return true;
}
bool SoundEngine::unpersist(InputPersistenceBlock &reader) {
- warning("STUB: SoundEngine::unpersist()");
+ _mixer->stopAll();
- return true;
+ if (reader.getVersion() < 2)
+ return true;
+
+ reader.read(_maxHandleId);
+
+ for (uint i = 0; i < SOUND_HANDLES; i++) {
+ reader.read(_handles[i].id);
+
+ Common::String fileName;
+ int sndType;
+ float volume;
+ float pan;
+ bool loop;
+ int loopStart;
+ int loopEnd;
+ uint layer;
+
+ reader.readString(fileName);
+ reader.read(sndType);
+ reader.read(volume);
+ reader.read(pan);
+ reader.read(loop);
+ reader.read(loopStart);
+ reader.read(loopEnd);
+ reader.read(layer);
+
+ if (reader.isGood()) {
+ playSoundEx(fileName, (SOUND_TYPES)sndType, volume, pan, loop, loopStart, loopEnd, layer, i);
+ } else
+ return false;
+ }
+
+ return reader.isGood();
}
diff --git a/engines/sword25/sfx/soundengine.h b/engines/sword25/sfx/soundengine.h
index 71f1602484..8132ec556e 100644
--- a/engines/sword25/sfx/soundengine.h
+++ b/engines/sword25/sfx/soundengine.h
@@ -65,6 +65,15 @@ struct SndHandle {
Audio::SoundHandle handle;
sndHandleType type;
uint32 id;
+
+ Common::String fileName;
+ int sndType;
+ float volume;
+ float pan;
+ bool loop;
+ int loopStart;
+ int loopEnd;
+ uint layer;
};
@@ -176,7 +185,7 @@ public:
* @remark If more control is needed over the playing, eg. changing the sound parameters
* for Volume and Panning, then PlaySoundEx should be used.
*/
- uint playSoundEx(const Common::String &fileName, SOUND_TYPES type, float volume = 1.0f, float pan = 0.0f, bool loop = false, int loopStart = -1, int loopEnd = -1, uint layer = 0);
+ uint playSoundEx(const Common::String &fileName, SOUND_TYPES type, float volume = 1.0f, float pan = 0.0f, bool loop = false, int loopStart = -1, int loopEnd = -1, uint layer = 0, uint handleId = 0x1337);
/**
* Sets the volume of a playing sound