aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordi Vilalta Prat2009-01-13 23:22:47 +0000
committerJordi Vilalta Prat2009-01-13 23:22:47 +0000
commit215af6f3b41a0460be6333aa1a4be50e8033fa63 (patch)
tree9a0716f6914afc956f2b1f05dc304148aad7ae32
parentcd7ab24dd64210fccd19563467d302d5adb02004 (diff)
downloadscummvm-rg350-215af6f3b41a0460be6333aa1a4be50e8033fa63.tar.gz
scummvm-rg350-215af6f3b41a0460be6333aa1a4be50e8033fa63.tar.bz2
scummvm-rg350-215af6f3b41a0460be6333aa1a4be50e8033fa63.zip
Reduced savegame code duplication and added savegame format versioning.
svn-id: r35855
-rw-r--r--engines/groovie/detection.cpp74
-rw-r--r--engines/groovie/module.mk1
-rw-r--r--engines/groovie/saveload.cpp168
-rw-r--r--engines/groovie/saveload.h51
-rw-r--r--engines/groovie/script.cpp67
5 files changed, 260 insertions, 101 deletions
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index fef63c3c74..e29a387e46 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -26,6 +26,7 @@
#include "common/savefile.h"
#include "groovie/groovie.h"
+#include "groovie/saveload.h"
namespace Groovie {
@@ -200,6 +201,7 @@ public:
SaveStateList listSaves(const char *target) const;
int getMaximumSaveSlot() const;
void removeSaveState(const char *target, int slot) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
bool GroovieMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *gd) const {
@@ -213,76 +215,38 @@ bool GroovieMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave);
- //(f == kSavesSupportCreationDate)
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo);
}
SaveStateList GroovieMetaEngine::listSaves(const char *target) const {
- Common::SaveFileManager *sfm = g_system->getSavefileManager();
- SaveStateList list;
-
- // Get the list of savefiles
- Common::String pattern = Common::String(target) + ".00?";
- Common::StringList savefiles = sfm->listSavefiles(pattern.c_str());
-
- // Sort the list of filenames
- sort(savefiles.begin(), savefiles.end());
-
- // Fill the information for the existing savegames
- Common::StringList::iterator it = savefiles.begin();
- while (it != savefiles.end()) {
- int slot = it->lastChar() - '0';
- if (slot >= 0 && slot <= 9) {
- Common::InSaveFile *file = sfm->openForLoading(it->c_str());
-
- // Read the savegame description
- Common::String description;
- unsigned char c = 1;
- for (int i = 0; (c != 0) && (i < 15); i++) {
- c = file->readByte();
- switch (c) {
- case 0:
- break;
- case 16: // @
- c = ' ';
- break;
- case 244: // $
- c = 0;
- break;
- default:
- c += 0x30;
- }
- if (c != 0) {
- description += c;
- }
- }
- delete file;
-
- list.push_back(SaveStateDescriptor(slot, description));
- }
- it++;
- }
-
- return list;
+ return SaveLoad::listValidSaves(target);
}
int GroovieMetaEngine::getMaximumSaveSlot() const {
- return 9;
+ return SaveLoad::getMaximumSlot();
}
void GroovieMetaEngine::removeSaveState(const char *target, int slot) const {
- if (slot < 0 || slot > 9) {
+ if (!SaveLoad::isSlotValid(slot)) {
// Invalid slot, do nothing
return;
}
- char extension[6];
- snprintf(extension, sizeof(extension), ".00%01d", slot);
+ Common::String filename = SaveLoad::getSlotSaveName(target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename.c_str());
+}
- Common::String filename = target;
- filename += extension;
+SaveStateDescriptor GroovieMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ SaveStateDescriptor desc;
- g_system->getSavefileManager()->removeSavefile(filename.c_str());
+ Common::InSaveFile *savefile = SaveLoad::openForLoading(target, slot, &desc);
+ if (savefile) {
+ // Loaded correctly
+ delete savefile;
+ }
+
+ return desc;
}
} // End of namespace Groovie
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index d4216d3437..1e89ff66f5 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
player.o \
resource.o \
roq.o \
+ saveload.o \
script.o \
vdx.o
diff --git a/engines/groovie/saveload.cpp b/engines/groovie/saveload.cpp
new file mode 100644
index 0000000000..0d719ed599
--- /dev/null
+++ b/engines/groovie/saveload.cpp
@@ -0,0 +1,168 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "groovie/saveload.h"
+
+#include "common/system.h"
+
+#define SUPPORTED_SAVEFILE_VERSION 1
+// 0 - Just script variables, compatible with the original
+// 1 - Added one byte with version number at the beginning
+
+namespace Groovie {
+
+int SaveLoad::getMaximumSlot() {
+ return 9;
+}
+
+bool SaveLoad::isSlotValid(int slot) {
+ return slot >= 0 && slot <= getMaximumSlot();
+}
+
+Common::String SaveLoad::getSlotSaveName(const Common::String &target, int slot) {
+ return target + ".00" + ('0' + slot);
+}
+
+SaveStateList SaveLoad::listValidSaves(const Common::String &target) {
+ SaveStateList list;
+
+ // Get the list of savefiles
+ Common::String pattern = target + ".00?";
+ Common::StringList savefiles = g_system->getSavefileManager()->listSavefiles(pattern.c_str());
+
+ // Sort the list of filenames
+ sort(savefiles.begin(), savefiles.end());
+
+ // Fill the information for the existing savegames
+ Common::StringList::iterator it = savefiles.begin();
+ while (it != savefiles.end()) {
+ int slot = it->lastChar() - '0';
+ SaveStateDescriptor descriptor;
+ Common::InSaveFile *file = SaveLoad::openForLoading(target, slot, &descriptor);
+ if (file) {
+ // It's a valid savefile, save the descriptor
+ delete file;
+ list.push_back(descriptor);
+ }
+ it++;
+ }
+
+ return list;
+}
+
+Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, int slot, SaveStateDescriptor *descriptor) {
+ // Validate the slot number
+ if (!isSlotValid(slot)) {
+ return NULL;
+ }
+
+ // Open the savefile
+ Common::String savename = getSlotSaveName(target, slot);
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(savename.c_str());
+ if (!savefile) {
+ return NULL;
+ }
+
+ // Read the savefile version
+ uint8 version;
+ if (savefile->size() == 1024) {
+ version = 0;
+ } else {
+ version = savefile->readByte();
+ }
+
+ // Verify we can read this version
+ if (version > SUPPORTED_SAVEFILE_VERSION) {
+ //TODO: show the error about unsupported savefile version
+ }
+
+ // Save the current position as the start for the engine data
+ int metaDataSize = savefile->pos();
+
+ // Fill the SaveStateDescriptor if it was provided
+ if (descriptor) {
+ // Initialize the SaveStateDescriptor
+ descriptor->setVal("save_slot", Common::String('0' + slot));
+ descriptor->setDeletableFlag(true);
+ descriptor->setWriteProtectedFlag(false);
+
+ // TODO: Add extra information
+ //setSaveDate(int year, int month, int day)
+ //setSaveTime(int hour, int min)
+ //setPlayTime(int hours, int minutes)
+
+ // Read the savegame description
+ Common::String description;
+ unsigned char c = 1;
+ for (int i = 0; (c != 0) && (i < 15); i++) {
+ c = savefile->readByte();
+ switch (c) {
+ case 0:
+ break;
+ case 16: // @
+ c = ' ';
+ break;
+ case 244: // $
+ c = 0;
+ break;
+ default:
+ c += 0x30;
+ }
+ if (c != 0) {
+ description += c;
+ }
+ }
+ descriptor->setVal("description", description);
+ }
+
+ // Return a substream, skipping the metadata
+ Common::SeekableSubReadStream *sub = new Common::SeekableSubReadStream(savefile, metaDataSize, savefile->size(), true);
+
+ // Move to the beginning of the substream
+ sub->seek(0, SEEK_SET);
+
+ return sub;
+}
+
+Common::OutSaveFile *SaveLoad::openForSaving(const Common::String &target, int slot) {
+ // Validate the slot number
+ if (!isSlotValid(slot)) {
+ return NULL;
+ }
+
+ // Open the savefile
+ Common::String savename = getSlotSaveName(target, slot);
+ Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(savename.c_str());
+ if (!savefile) {
+ return NULL;
+ }
+
+ // Write the savefile version
+ savefile->writeByte(SUPPORTED_SAVEFILE_VERSION);
+
+ return savefile;
+}
+
+} // End of Groovie namespace
diff --git a/engines/groovie/saveload.h b/engines/groovie/saveload.h
new file mode 100644
index 0000000000..b2b81cb6db
--- /dev/null
+++ b/engines/groovie/saveload.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GROOVIE_SAVELOAD_H
+#define GROOVIE_SAVELOAD_H
+
+#include "common/savefile.h"
+#include "engines/game.h"
+
+namespace Groovie {
+
+class SaveLoad {
+public:
+ // Validating slot numbers
+ static int getMaximumSlot();
+ static bool isSlotValid(int slot);
+
+ // Getting information
+ static Common::String getSlotSaveName(const Common::String &target, int slot);
+ static SaveStateList listValidSaves(const Common::String &target);
+
+ // Opening savefiles
+ static Common::InSaveFile *openForLoading(const Common::String &target, int slot, SaveStateDescriptor *descriptor = NULL);
+ static Common::OutSaveFile *openForSaving(const Common::String &target, int slot);
+};
+
+} // End of Groovie namespace
+
+#endif // GROOVIE_SAVELOAD_H
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index d6ae566012..f36298a497 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -28,11 +28,11 @@
#include "groovie/script.h"
#include "groovie/groovie.h"
#include "groovie/cell.h"
+#include "groovie/saveload.h"
#include "common/config-manager.h"
#include "common/endian.h"
#include "common/events.h"
-#include "common/savefile.h"
#define NUM_OPCODES 90
@@ -360,8 +360,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
}
void Script::loadgame(uint slot) {
- Common::String filename = ConfMan.getActiveDomainName() + ".00" + ('0' + slot);
- Common::InSaveFile *file = _vm->_system->getSavefileManager()->openForLoading(filename.c_str());
+ Common::InSaveFile *file = SaveLoad::openForLoading(ConfMan.getActiveDomainName(), slot);
// Loading the variables. It is endian safe because they're byte variables
file->read(_variables, 0x400);
@@ -372,11 +371,13 @@ void Script::loadgame(uint slot) {
void Script::savegame(uint slot) {
char save[15];
char newchar;
- Common::String filename = ConfMan.getActiveDomainName() + ".00" + ('0' + slot);
- Common::OutSaveFile *file = _vm->_system->getSavefileManager()->openForSaving(filename.c_str());
+ Common::OutSaveFile *file = SaveLoad::openForSaving(ConfMan.getActiveDomainName(), slot);
// Saving the variables. It is endian safe because they're byte variables
file->write(_variables, 0x400);
+ delete file;
+
+ // Cache the saved name
for (int i = 0; i < 15; i++) {
newchar = _variables[i] + 0x30;
if ((newchar < 0x30 || newchar > 0x39) && (newchar < 0x41 || newchar > 0x7A)) {
@@ -387,8 +388,6 @@ void Script::savegame(uint slot) {
}
}
_saveNames[slot] = save;
-
- delete file;
}
// OPCODES
@@ -1217,8 +1216,6 @@ void Script::o_hotspot_slot() {
Common::Rect rect(left, top, right, bottom);
if (hotspot(rect, address, cursor)) {
- char savename[15];
-
if (_hotspotSlot == slot) {
return;
}
@@ -1227,8 +1224,7 @@ void Script::o_hotspot_slot() {
if (!_font) {
_font = new Font(_vm->_system);
}
- strcpy(savename, _saveNames[slot].c_str());
- _font->printstring(savename);
+ _font->printstring(_saveNames[slot].c_str());
// Save the currently highlighted slot
_hotspotSlot = slot;
@@ -1252,54 +1248,33 @@ void Script::o_hotspot_slot() {
void Script::o_checkvalidsaves() {
debugScript(1, true, "CHECKVALIDSAVES");
- // Reset the array of valid saves
+ // Reset the array of valid saves and the savegame names cache
for (int i = 0; i < 10; i++) {
setVariable(i, 0);
+ _saveNames[i] = "E M P T Y";
}
// Get the list of savefiles
- Common::String pattern = ConfMan.getActiveDomainName() + ".00?";
- Common::StringList savefiles = _vm->_system->getSavefileManager()->listSavefiles(pattern.c_str());
+ SaveStateList list = SaveLoad::listValidSaves(ConfMan.getActiveDomainName());
// Mark the existing savefiles as valid
uint count = 0;
- Common::StringList::iterator it = savefiles.begin();
- while (it != savefiles.end()) {
- int8 n = it->lastChar() - '0';
- if (n >= 0 && n <= 9) {
- // TODO: Check the contents of the file?
- debugScript(2, true, " Found valid savegame: %s", it->c_str());
- setVariable(n, 1);
+ SaveStateList::iterator it = list.begin();
+ while (it != list.end()) {
+ int8 slot = it->getVal("save_slot").lastChar() - '0';
+ if (SaveLoad::isSlotValid(slot)) {
+ debugScript(2, true, " Found valid savegame: %s", it->getVal("description").c_str());
+
+ // Mark this slot as used
+ setVariable(slot, 1);
+
+ // Cache this slot's description
+ _saveNames[slot] = it->getVal("description");
count++;
}
it++;
}
- for (int slots = 0; slots < 10; slots++) {
- char savename[15];
- Common::String filename = ConfMan.getActiveDomainName() + ".00" + ('0' + slots);
- Common::StringList files = _vm->_system->getSavefileManager()->listSavefiles(filename.c_str());
- if (!files.empty()) {
- Common::InSaveFile *file = _vm->_system->getSavefileManager()->openForLoading(filename.c_str());
- if (file) {
- uint8 i;
- char temp;
-
- for (i = 0; i < 15; i++) {
- file->read(&temp, 1);
- savename[i] = temp + 0x30;
- }
-
- delete file;
- } else {
- strcpy(savename, "ERROR");
- }
- } else {
- strcpy(savename, "E M P T Y");
- }
- _saveNames[slots] = savename;
- }
-
// Save the number of valid saves
setVariable(0x104, count);
debugScript(1, true, " Found %d valid savegames", count);