aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorBenjamin Haisch2008-11-13 00:16:13 +0000
committerWillem Jan Palenstijn2011-11-20 22:43:07 +0100
commit9e78b5d393cadd6ce426f0184e136a38579c819a (patch)
treecd0c6d2352ef4c55849c0cf7763dffbaa1830d0b /engines
parent47ae9085899a41f5ed5204183b008d4bff7c4a31 (diff)
downloadscummvm-rg350-9e78b5d393cadd6ce426f0184e136a38579c819a.tar.gz
scummvm-rg350-9e78b5d393cadd6ce426f0184e136a38579c819a.tar.bz2
scummvm-rg350-9e78b5d393cadd6ce426f0184e136a38579c819a.zip
TOLTECS: - Listing savestates via command line or Launcher
- Loading/Saving during run time Other savestate functions yet todo. I'll probably remove the "original" in-game menu and move everything to the GMM.
Diffstat (limited to 'engines')
-rw-r--r--engines/toltecs/detection.cpp119
-rw-r--r--engines/toltecs/movie.cpp4
-rw-r--r--engines/toltecs/saveload.cpp80
-rw-r--r--engines/toltecs/toltecs.cpp32
-rw-r--r--engines/toltecs/toltecs.h46
5 files changed, 250 insertions, 31 deletions
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index 39915a55a2..9128ce53a8 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -56,7 +56,7 @@ namespace Toltecs {
static const ToltecsGameDescription gameDescriptions[] = {
{
- // Toltecs English version
+ // 3 Skulls of the Toltecs English version
{
"toltecs",
0,
@@ -67,8 +67,8 @@ static const ToltecsGameDescription gameDescriptions[] = {
},
},
-
{
+ // 3 Skulls of the Toltecs Russian version
{
"toltecs",
0,
@@ -115,9 +115,30 @@ public:
return "Toltecs Engine (C) 1996";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+ SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const;
+ void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
+bool ToltecsMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+// (f == kSupportsLoadingDuringStartup) ||
+// (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail);
+}
+
+bool Toltecs::ToltecsEngine::hasFeature(EngineFeature f) const {
+ return
+// (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
const Toltecs::ToltecsGameDescription *gd = (const Toltecs::ToltecsGameDescription *)desc;
if (gd) {
@@ -126,6 +147,100 @@ bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Com
return gd != 0;
}
+SaveStateList ToltecsMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Toltecs::ToltecsEngine::SaveHeader header;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ Common::StringList filenames;
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 999) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
+ if (in) {
+ if (Toltecs::ToltecsEngine::readSaveHeader(in, false, header) == Toltecs::ToltecsEngine::kRSHENoError) {
+ saveList.push_back(SaveStateDescriptor(slotNum, header.description));
+ }
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+int ToltecsMetaEngine::getMaximumSaveSlot() const {
+ return 999;
+}
+
+void ToltecsMetaEngine::removeSaveState(const char *target, int slot) const {
+ // Slot 0 can't be deleted, it's for restarting the game(s)
+ if (slot == 0)
+ return;
+
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::String filename = Toltecs::ToltecsEngine::getSavegameFilename(target, slot);
+
+ saveFileMan->removeSavefile(filename.c_str());
+
+ Common::StringList filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+ filenames = saveFileMan->listSavefiles(pattern.c_str());
+ Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 3);
+
+ // Rename every slot greater than the deleted slot,
+ // Also do not rename quicksaves.
+ if (slotNum > slot && slotNum < 990) {
+ // FIXME: Our savefile renaming done here is inconsitent with what we do in
+ // GUI_v2::deleteMenu. While here we rename every slot with a greater equal
+ // number of the deleted slot to deleted slot, deleted slot + 1 etc.,
+ // we only rename the following slots in GUI_v2::deleteMenu until a slot
+ // is missing.
+ saveFileMan->renameSavefile(file->c_str(), filename.c_str());
+
+ filename = Toltecs::ToltecsEngine::getSavegameFilename(target, ++slot);
+ }
+ }
+
+}
+
+SaveStateDescriptor ToltecsMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = Toltecs::ToltecsEngine::getSavegameFilename(target, slot);
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
+
+ if (in) {
+ Toltecs::ToltecsEngine::SaveHeader header;
+ Toltecs::ToltecsEngine::kReadSaveHeaderError error;
+
+ error = Toltecs::ToltecsEngine::readSaveHeader(in, true, header);
+ delete in;
+
+ if (error == Toltecs::ToltecsEngine::kRSHENoError) {
+ SaveStateDescriptor desc(slot, header.description);
+
+ desc.setDeletableFlag(false);
+ desc.setWriteProtectedFlag(false);
+ desc.setThumbnail(header.thumbnail);
+
+ return desc;
+ }
+ }
+
+ return SaveStateDescriptor();
+}
+
#if PLUGIN_ENABLED_DYNAMIC(TOLTECS)
REGISTER_PLUGIN_DYNAMIC(TOLTECS, PLUGIN_TYPE_ENGINE, ToltecsMetaEngine);
#else
diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp
index 2813c0ea69..9cbcbb2ed6 100644
--- a/engines/toltecs/movie.cpp
+++ b/engines/toltecs/movie.cpp
@@ -52,6 +52,8 @@ void MoviePlayer::playMovie(uint resIndex) {
uint32 subtitleSlot;
byte moviePalette[768];
+ _vm->_isSaveAllowed = false;
+
memset(moviePalette, 0, sizeof(moviePalette));
_vm->_screen->finishTalkTextItems();
@@ -176,6 +178,8 @@ void MoviePlayer::playMovie(uint resIndex) {
debug(0, "playMovie() done");
+ _vm->_isSaveAllowed = true;
+
}
void MoviePlayer::fetchAudioChunks() {
diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp
index b631b1d529..da62da40f4 100644
--- a/engines/toltecs/saveload.cpp
+++ b/engines/toltecs/saveload.cpp
@@ -30,6 +30,8 @@
#include "base/plugins.h"
#include "base/version.h"
+#include "graphics/thumbnail.h"
+
#include "sound/mixer.h"
#include "toltecs/toltecs.h"
@@ -44,14 +46,43 @@ namespace Toltecs {
/* TODO:
- Saveload is working so far but only one slot is supported until the game menu is implemented
- - Save with F6; Load with F9
+ - Save with F7; Load with F9
- Saving during an animation (AnimationPlayer) is not working correctly yet
- Maybe switch to SCUMM/Tinsel serialization approach?
*/
#define SAVEGAME_VERSION 0 // 0 is dev version until in official SVN
-void ToltecsEngine::savegame(const char *filename) {
+ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
+
+ header.version = in->readUint32LE();
+ if (header.version != SAVEGAME_VERSION)
+ return kRSHEInvalidVersion;
+
+ byte descriptionLen = in->readByte();
+ header.description = "";
+ while (descriptionLen--)
+ header.description += (char)in->readByte();
+
+ if (loadThumbnail) {
+ header.thumbnail = new Graphics::Surface();
+ assert(header.thumbnail);
+ if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
+ delete header.thumbnail;
+ header.thumbnail = 0;
+ }
+ } else {
+ Graphics::skipThumbnailHeader(*in);
+ }
+
+ // Not used yet, reserved for future usage
+ header.gameID = in->readByte();
+ header.flags = in->readUint32LE();
+
+ return (in->ioFailed() ? kRSHEIoError : kRSHENoError);
+}
+
+void ToltecsEngine::savegame(const char *filename, const char *description) {
Common::OutSaveFile *out;
if (!(out = g_system->getSavefileManager()->openForSaving(filename))) {
@@ -61,6 +92,16 @@ void ToltecsEngine::savegame(const char *filename) {
out->writeUint32LE(SAVEGAME_VERSION);
+ byte descriptionLen = strlen(description);
+ out->writeByte(descriptionLen);
+ out->write(description, descriptionLen);
+
+ Graphics::saveThumbnail(*out);
+
+ // Not used yet, reserved for future usage
+ out->writeByte(0);
+ out->writeUint32LE(0);
+
out->writeUint16LE(_cameraX);
out->writeUint16LE(_cameraY);
out->writeUint16LE(_cameraHeight);
@@ -99,10 +140,14 @@ void ToltecsEngine::loadgame(const char *filename) {
warning("Can't open file '%s', game not loaded", filename);
return;
}
+
+ SaveHeader header;
+
+ kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
- uint32 version = in->readUint32LE();
- if (version != SAVEGAME_VERSION) {
- warning("Savegame '%s' too old, game not loaded (got v%d, need v%d)", filename, version, SAVEGAME_VERSION);
+ if (errorCode != kRSHENoError) {
+ warning("Error loading savegame '%s'", filename);
+ delete in;
return;
}
@@ -145,4 +190,29 @@ void ToltecsEngine::loadgame(const char *filename) {
}
+Common::Error ToltecsEngine::loadGameState(int slot) {
+ const char *fileName = getSavegameFilename(slot);
+ loadgame(fileName);
+}
+
+Common::Error ToltecsEngine::saveGameState(int slot, const char *description) {
+ const char *fileName = getSavegameFilename(slot);
+ savegame(fileName, description);
+}
+
+const char *ToltecsEngine::getSavegameFilename(int num) {
+ static Common::String filename;
+ filename = getSavegameFilename(_targetName, num);
+ return filename.c_str();
+}
+
+Common::String ToltecsEngine::getSavegameFilename(const Common::String &target, int num) {
+ assert(num >= 0 && num <= 999);
+
+ char extension[5];
+ sprintf(extension, "%03d", num);
+
+ return target + "." + extension;
+}
+
} // End of namespace Toltecs
diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp
index 4691d23cb2..6e65999737 100644
--- a/engines/toltecs/toltecs.cpp
+++ b/engines/toltecs/toltecs.cpp
@@ -79,16 +79,28 @@ ToltecsEngine::~ToltecsEngine() {
delete _rnd;
}
-int ToltecsEngine::init() {
+Common::Error ToltecsEngine::init() {
// Initialize backend
_system->beginGFXTransaction();
initCommonGFX(true);
_system->initSize(640, 400);
_system->endGFXTransaction();
- return 0;
+ return Common::kNoError;
}
-int ToltecsEngine::go() {
+void ToltecsEngine::syncSoundSettings() {
+ /*
+ _music->setVolume(ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+ */
+}
+
+Common::Error ToltecsEngine::go() {
+
+ _isSaveAllowed = true;
_quitGame = false;
_counter01 = 0;
@@ -140,16 +152,6 @@ int ToltecsEngine::go() {
_system->showMouse(true);
-//#define TEST_MOVIE
-#ifdef TEST_MOVIE
- _screen->registerFont(0, 0x0D);
- _screen->registerFont(1, 0x0E);
- //_moviePlayer->playMovie(0x000012D8);
- //_moviePlayer->playMovie(0x000012D7);
- //_moviePlayer->playMovie(0x);
- _moviePlayer->playMovie(0x000012E0);
-#endif
-
//#define TEST_MENU
#ifdef TEST_MENU
_screen->registerFont(0, 0x0D);
@@ -183,7 +185,7 @@ int ToltecsEngine::go() {
delete _sound;
- return 0;
+ return Common::kNoError;
}
void ToltecsEngine::loadScene(uint resIndex) {
@@ -259,7 +261,7 @@ void ToltecsEngine::updateInput() {
// FIXME: This is just for debugging
switch (event.kbd.keycode) {
case Common::KEYCODE_F7:
- savegame("toltecs.001");
+ savegame("toltecs.001", "Quicksave");
break;
case Common::KEYCODE_F9:
loadgame("toltecs.001");
diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h
index b9d08c3d59..0794a26b9d 100644
--- a/engines/toltecs/toltecs.h
+++ b/engines/toltecs/toltecs.h
@@ -43,10 +43,6 @@
namespace Toltecs {
-enum ToltecsGameFeatures {
- GF_PACKED = (1 << 0)
-};
-
struct ToltecsGameDescription;
class AnimationPlayer;
@@ -65,14 +61,17 @@ class ToltecsEngine : public ::Engine {
Common::KeyState _keyPressed;
protected:
- int init();
- int go();
+ Common::Error init();
+ Common::Error go();
// void shutdown();
public:
ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc);
virtual ~ToltecsEngine();
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual void syncSoundSettings();
+
Common::RandomSource *_rnd;
const ToltecsGameDescription *_gameDescription;
uint32 getFeatures() const;
@@ -99,10 +98,8 @@ public:
int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize);
- void savegame(const char *filename);
- void loadgame(const char *filename);
-
public:
+
AnimationPlayer *_anim;
ArchiveReader *_arc;
Input *_input;
@@ -140,6 +137,37 @@ public:
int16 _mouseDisabled;
bool _leftButtonDown, _rightButtonDown;
+ /* Save/load */
+
+ enum kReadSaveHeaderError {
+ kRSHENoError = 0,
+ kRSHEInvalidType = 1,
+ kRSHEInvalidVersion = 2,
+ kRSHEIoError = 3
+ };
+
+ struct SaveHeader {
+ Common::String description;
+ uint32 version;
+ byte gameID;
+ uint32 flags;
+ Graphics::Surface *thumbnail;
+ };
+
+ bool _isSaveAllowed;
+
+ bool canLoadGameStateCurrently() { return _isSaveAllowed; }
+ bool canSaveGameStateCurrently() { return _isSaveAllowed; }
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const char *description);
+ void savegame(const char *filename, const char *description);
+ void loadgame(const char *filename);
+
+ const char *getSavegameFilename(int num);
+ static Common::String getSavegameFilename(const Common::String &target, int num);
+
+ static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
+
};
} // End of namespace Toltecs