mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 14:51:40 +00:00
SWORD25: Implement persistence functions for soundengine
Now sound is properly saved/restored. Implemented savegame versioning. Compatibility with old saves pertained.
This commit is contained in:
parent
c32a3ea0d3
commit
15a16e556c
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,18 +204,30 @@ 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;
|
||||
|
||||
if (handleId == 0x1337)
|
||||
handle = getHandle(&id);
|
||||
else
|
||||
handle = &_handles[handleId];
|
||||
|
||||
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);
|
||||
|
||||
handle->type = kAllocatedHandle;
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
_mixer->playStream(getType(type), &(handle->handle), stream, -1, (byte)(volume * 255), (int8)(pan * 127));
|
||||
#endif
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user