aboutsummaryrefslogtreecommitdiff
path: root/engines/zvision/file
diff options
context:
space:
mode:
Diffstat (limited to 'engines/zvision/file')
-rw-r--r--engines/zvision/file/save_manager.cpp290
-rw-r--r--engines/zvision/file/save_manager.h110
-rw-r--r--engines/zvision/file/search_manager.cpp16
-rw-r--r--engines/zvision/file/search_manager.h18
4 files changed, 422 insertions, 12 deletions
diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp
new file mode 100644
index 0000000000..042fafd38e
--- /dev/null
+++ b/engines/zvision/file/save_manager.cpp
@@ -0,0 +1,290 @@
+/* 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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/zvision.h"
+#include "zvision/file/save_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+
+#include "common/system.h"
+#include "common/translation.h"
+
+#include "graphics/surface.h"
+#include "graphics/thumbnail.h"
+
+#include "gui/message.h"
+#include "gui/saveload.h"
+
+namespace ZVision {
+
+const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G');
+
+bool SaveManager::scummVMSaveLoadDialog(bool isSave) {
+ GUI::SaveLoadChooser *dialog;
+ Common::String desc;
+ int slot;
+
+ if (isSave) {
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ slot = dialog->runModalWithCurrentTarget();
+ desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ // create our own description for the saved game, the user didnt enter it
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+
+ if (desc.size() > 28)
+ desc = Common::String(desc.c_str(), 28);
+ } else {
+ dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ slot = dialog->runModalWithCurrentTarget();
+ }
+
+ delete dialog;
+
+ if (slot < 0)
+ return false;
+
+ if (isSave) {
+ saveGame(slot, desc);
+ return true;
+ } else {
+ Common::ErrorCode result = loadGame(slot).getCode();
+ return (result == Common::kNoError);
+ }
+}
+
+void SaveManager::saveGame(uint slot, const Common::String &saveName) {
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
+
+ writeSaveGameHeader(file, saveName);
+
+ _engine->getScriptManager()->serialize(file);
+
+ file->finalize();
+ delete file;
+
+ _lastSaveTime = g_system->getMillis();
+}
+
+void SaveManager::saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream) {
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(_engine->generateSaveFileName(slot));
+
+ writeSaveGameHeader(file, saveName);
+
+ file->write(stream->getData(), stream->size());
+
+ file->finalize();
+ delete file;
+
+ _lastSaveTime = g_system->getMillis();
+}
+
+void SaveManager::saveGameBuffered(uint slot, const Common::String &saveName) {
+ if (_tempSave) {
+ saveGame(slot, saveName, _tempSave);
+ flushSaveBuffer();
+ }
+}
+
+void SaveManager::autoSave() {
+ saveGame(0, "Auto save");
+}
+
+void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName) {
+ file->writeUint32BE(SAVEGAME_ID);
+
+ // Write version
+ file->writeByte(SAVE_VERSION);
+
+ // Write savegame name
+ file->writeString(saveName);
+ file->writeByte(0);
+
+ // Create a thumbnail and save it
+ Graphics::saveThumbnail(*file);
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ file->writeSint16LE(td.tm_year + 1900);
+ file->writeSint16LE(td.tm_mon + 1);
+ file->writeSint16LE(td.tm_mday);
+ file->writeSint16LE(td.tm_hour);
+ file->writeSint16LE(td.tm_min);
+}
+
+Common::Error SaveManager::loadGame(uint slot) {
+ Common::SeekableReadStream *saveFile = getSlotFile(slot);
+ if (saveFile == 0) {
+ return Common::kPathDoesNotExist;
+ }
+
+ // Read the header
+ SaveGameHeader header;
+ if (!readSaveGameHeader(saveFile, header)) {
+ return Common::kUnknownError;
+ }
+
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Update the state table values
+ scriptManager->deserialize(saveFile);
+
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
+
+ return Common::kNoError;
+}
+
+Common::Error SaveManager::loadGame(const Common::String &saveName) {
+ Common::File *saveFile = _engine->getSearchManager()->openFile(saveName);
+ if (saveFile == NULL) {
+ saveFile = new Common::File;
+ if (!saveFile->open(saveName)) {
+ delete saveFile;
+ return Common::kPathDoesNotExist;
+ }
+ }
+
+ // Read the header
+ SaveGameHeader header;
+ if (!readSaveGameHeader(saveFile, header)) {
+ return Common::kUnknownError;
+ }
+
+ ScriptManager *scriptManager = _engine->getScriptManager();
+ // Update the state table values
+ scriptManager->deserialize(saveFile);
+
+ delete saveFile;
+ if (header.thumbnail)
+ delete header.thumbnail;
+
+ return Common::kNoError;
+}
+
+bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
+ uint32 tag = in->readUint32BE();
+ // Check if it's original savegame than fill header structure
+ if (tag == MKTAG('Z', 'N', 'S', 'G')) {
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.saveName = "Original Save";
+ header.thumbnail = NULL;
+ header.version = SAVE_ORIGINAL;
+ in->seek(-4, SEEK_CUR);
+ return true;
+ }
+ if (tag != SAVEGAME_ID) {
+ warning("File is not a ZVision save file. Aborting load");
+ return false;
+ }
+
+ // Read in the version
+ header.version = in->readByte();
+
+ // Check that the save version isn't newer than this binary
+ if (header.version > SAVE_VERSION) {
+ uint tempVersion = header.version;
+ GUI::MessageDialog dialog(
+ Common::String::format(
+ "This save file uses version %u, but this engine only "
+ "supports up to version %d. You will need an updated version "
+ "of the engine to use this save file.", tempVersion, SAVE_VERSION
+ ),
+ "OK");
+ dialog.runModal();
+ }
+
+ // Read in the save name
+ header.saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0')
+ header.saveName += ch;
+
+ // Get the thumbnail
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
+ return false;
+
+ // Read in save date/time
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
+ header.saveMinutes = in->readSint16LE();
+
+ return true;
+}
+
+Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) {
+ Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->generateSaveFileName(slot));
+ if (saveFile == NULL) {
+ // Try to load standard save file
+ Common::String filename;
+ if (_engine->getGameId() == GID_GRANDINQUISITOR)
+ filename = Common::String::format("inqsav%u.sav", slot);
+ else if (_engine->getGameId() == GID_NEMESIS)
+ filename = Common::String::format("nemsav%u.sav", slot);
+
+ saveFile = _engine->getSearchManager()->openFile(filename);
+ if (saveFile == NULL) {
+ Common::File *tmpFile = new Common::File;
+ if (!tmpFile->open(filename)) {
+ delete tmpFile;
+ } else {
+ saveFile = tmpFile;
+ }
+ }
+
+ }
+
+ return saveFile;
+}
+
+void SaveManager::prepareSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = new Common::MemoryWriteStreamDynamic;
+
+ _engine->getScriptManager()->serialize(_tempSave);
+}
+
+void SaveManager::flushSaveBuffer() {
+ if (_tempSave)
+ delete _tempSave;
+
+ _tempSave = NULL;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h
new file mode 100644
index 0000000000..fc8db67566
--- /dev/null
+++ b/engines/zvision/file/save_manager.h
@@ -0,0 +1,110 @@
+/* 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.
+ *
+ */
+
+#ifndef ZVISION_SAVE_MANAGER_H
+#define ZVISION_SAVE_MANAGER_H
+
+#include "common/savefile.h"
+#include "common/memstream.h"
+
+namespace Common {
+class String;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+struct SaveGameHeader {
+ byte version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+};
+
+class SaveManager {
+public:
+ SaveManager(ZVision *engine) : _engine(engine), _tempSave(NULL), _lastSaveTime(0) {}
+ ~SaveManager() {
+ flushSaveBuffer();
+ }
+
+ uint32 getLastSaveTime() const {
+ return _lastSaveTime;
+ }
+
+private:
+ ZVision *_engine;
+ uint32 _lastSaveTime;
+ static const uint32 SAVEGAME_ID;
+
+ enum {
+ SAVE_ORIGINAL = 0,
+ SAVE_VERSION = 1
+ };
+
+ Common::MemoryWriteStreamDynamic *_tempSave;
+
+public:
+ /**
+ * Called every room change. Saves the state of the room just before
+ * the room changes.
+ */
+ void autoSave();
+ /**
+ * Copies the data from the last auto-save into a new save file. We
+ * can't use the current state data because the save menu *IS* a room.
+ * The file is named using ZVision::generateSaveFileName(slot)
+ *
+ * @param slot The save slot this save pertains to. Must be [1, 20]
+ * @param saveName The internal name for this save. This is NOT the name of the actual save file.
+ */
+ void saveGame(uint slot, const Common::String &saveName);
+ void saveGame(uint slot, const Common::String &saveName, Common::MemoryWriteStreamDynamic *stream);
+ void saveGameBuffered(uint slot, const Common::String &saveName);
+ /**
+ * Loads the state data from the save file that slot references. Uses
+ * ZVision::generateSaveFileName(slot) to get the save file name.
+ *
+ * @param slot The save slot to load. Must be [1, 20]
+ */
+ Common::Error loadGame(uint slot);
+ Common::Error loadGame(const Common::String &saveName);
+
+ Common::SeekableReadStream *getSlotFile(uint slot);
+ bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header);
+
+ void prepareSaveBuffer();
+ void flushSaveBuffer();
+ bool scummVMSaveLoadDialog(bool isSave);
+private:
+ void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName);
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp
index 30c269c290..ec250ff648 100644
--- a/engines/zvision/file/search_manager.cpp
+++ b/engines/zvision/file/search_manager.cpp
@@ -169,8 +169,13 @@ void SearchManager::loadZix(const Common::String &name) {
line.trim();
if (line.matchString("----------*", true))
break;
- else if (line.matchString("DIR:*", true)) {
+ else if (line.matchString("DIR:*", true) || line.matchString("CD0:*", true) || line.matchString("CD1:*", true)) {
Common::String path(line.c_str() + 5);
+ // Check if INQUIS.ZIX refers to the ZGI folder, and check the game
+ // root folder instead
+ if (path.hasPrefix("zgi\\"))
+ path = Common::String(path.c_str() + 4);
+
Common::Archive *arc;
char tempPath[128];
strcpy(tempPath, path.c_str());
@@ -265,7 +270,7 @@ void SearchManager::addDir(const Common::String &name) {
void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const Common::FSNode &fsNode, int depth) {
Common::FSList fsList;
- if ( fsNode.getChildren(fsList) ) {
+ if (fsNode.getChildren(fsList)) {
_list.push_back(fsNode.getPath());
@@ -275,4 +280,11 @@ void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const
}
}
+void SearchManager::listMembersWithExtension(MatchList &fileList, Common::String extension) {
+ for (SearchManager::MatchList::iterator it = _files.begin(); it != _files.end(); ++it) {
+ if (it->_key.hasSuffix(extension))
+ fileList[it->_key] = it->_value;
+ }
+}
+
} // End of namespace ZVision
diff --git a/engines/zvision/file/search_manager.h b/engines/zvision/file/search_manager.h
index fdd70fd381..b9ed02ec13 100644
--- a/engines/zvision/file/search_manager.h
+++ b/engines/zvision/file/search_manager.h
@@ -47,25 +47,23 @@ public:
void loadZix(const Common::String &name);
-private:
-
- void listDirRecursive(Common::List<Common::String> &dirList, const Common::FSNode &fsNode, int depth);
-
struct Node {
Common::String name;
Common::Archive *arch;
};
- Common::List<Common::String> _dirList;
-
typedef Common::HashMap<Common::String, Node, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MatchList;
- Common::List<Common::Archive *> _archList;
- MatchList _files;
-
- Common::String _root;
+ void listMembersWithExtension(MatchList &fileList, Common::String extension);
private:
+
+ void listDirRecursive(Common::List<Common::String> &dirList, const Common::FSNode &fsNode, int depth);
+
+ Common::List<Common::String> _dirList;
+ Common::List<Common::Archive *> _archList;
+ Common::String _root;
+ MatchList _files;
};
}