aboutsummaryrefslogtreecommitdiff
path: root/engines/agi
diff options
context:
space:
mode:
authorFilippos Karapetis2008-11-10 19:02:47 +0000
committerFilippos Karapetis2008-11-10 19:02:47 +0000
commit2b59700d2a311c0486912435624bac78fe1f9dbb (patch)
tree025ae9e8ed87c3ddd1c52d50e4ad8ab1b29a3039 /engines/agi
parenta859e2c1c925252b6c7693efb052bc2ff28915db (diff)
downloadscummvm-rg350-2b59700d2a311c0486912435624bac78fe1f9dbb.tar.gz
scummvm-rg350-2b59700d2a311c0486912435624bac78fe1f9dbb.tar.bz2
scummvm-rg350-2b59700d2a311c0486912435624bac78fe1f9dbb.zip
AGI save games now contain thumbnails and creation date/time (visible from the GMM save/load screens)
svn-id: r34989
Diffstat (limited to 'engines/agi')
-rw-r--r--engines/agi/agi.h6
-rw-r--r--engines/agi/detection.cpp104
-rw-r--r--engines/agi/preagi.h2
-rw-r--r--engines/agi/saveload.cpp41
4 files changed, 142 insertions, 11 deletions
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 2e4710744b..0dd20be283 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -724,6 +724,8 @@ public:
virtual void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) = 0;
virtual void releaseImageStack() = 0;
+ virtual int saveGame(const char *fileName, const char *saveName) = 0;
+ virtual int loadGame(const char *fileName, bool checkId = true) = 0;
int _soundemu;
@@ -738,6 +740,10 @@ public:
uint16 getGameType() const;
Common::Language getLanguage() const;
Common::Platform getPlatform() const;
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const char *desc);
+ bool canLoadGameStateCurrently();
+ bool canSaveGameStateCurrently();
};
class AgiEngine : public AgiBase {
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index bcc2b60d74..a9f49b64c6 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -28,6 +28,7 @@
#include "common/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
+#include "graphics/thumbnail.h"
#include "agi/agi.h"
#include "agi/preagi.h"
@@ -2127,7 +2128,8 @@ public:
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
-
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+
const Common::ADGameDescription *fallbackDetect(const Common::FSList &fslist) const;
};
@@ -2135,11 +2137,17 @@ bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave);
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate);
}
bool AgiBase::hasFeature(EngineFeature f) const {
- return (f == kSupportsRTL);
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
}
@@ -2197,13 +2205,67 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const {
int AgiMetaEngine::getMaximumSaveSlot() const { return 999; }
void AgiMetaEngine::removeSaveState(const char *target, int slot) const {
- char extension[6];
- snprintf(extension, sizeof(extension), ".%03d", slot);
+ char fileName[MAX_PATH];
+ sprintf(fileName, "%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ const uint32 AGIflag = MKID_BE('AGI:');
+ char fileName[MAX_PATH];
+ sprintf(fileName, "%s.%03d", target, slot);
+
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (in) {
+ if (in->readUint32BE() != AGIflag) {
+ delete in;
+ return SaveStateDescriptor();
+ }
+
+ char name[32];
+ in->read(name, 31);
+
+ SaveStateDescriptor desc(slot, name);
+
+ desc.setDeletableFlag(true);
+ desc.setWriteProtectedFlag(false);
+
+ char saveVersion = in->readByte();
+ if (saveVersion >= 4) {
+ Graphics::Surface *thumbnail = new Graphics::Surface();
+ assert(thumbnail);
+ if (!Graphics::loadThumbnail(*in, *thumbnail)) {
+ delete thumbnail;
+ thumbnail = 0;
+ }
+
+ desc.setThumbnail(thumbnail);
+
+ uint32 saveDate = in->readUint32BE();
+ uint16 saveTime = in->readUint16BE();
+
+ int day = (saveDate >> 24) & 0xFF;
+ int month = (saveDate >> 16) & 0xFF;
+ int year = saveDate & 0xFFFF;
+
+ desc.setSaveDate(year, month, day);
+
+ int hour = (saveTime >> 8) & 0xFF;
+ int minutes = saveTime & 0xFF;
- Common::String filename = target;
- filename += extension;
+ desc.setSaveTime(hour, minutes);
- g_system->getSavefileManager()->removeSavefile(filename.c_str());
+ // TODO: played time
+ }
+
+
+ delete in;
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
}
const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSList &fslist) const {
@@ -2375,3 +2437,29 @@ const Common::ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSL
#else
REGISTER_PLUGIN_STATIC(AGI, PLUGIN_TYPE_ENGINE, AgiMetaEngine);
#endif
+
+namespace Agi {
+
+Common::Error AgiBase::loadGameState(int slot) {
+ static char saveLoadSlot[12];
+ sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), slot);
+ loadGame(saveLoadSlot);
+ return Common::kNoError; // TODO: return success/failure
+}
+
+Common::Error AgiBase::saveGameState(int slot, const char *desc) {
+ static char saveLoadSlot[12];
+ sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), slot);
+ saveGame(saveLoadSlot, desc);
+ return Common::kNoError; // TODO: return success/failure
+}
+
+bool AgiBase::canLoadGameStateCurrently() {
+ return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork));
+}
+
+bool AgiBase::canSaveGameStateCurrently() {
+ return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork));
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/preagi.h b/engines/agi/preagi.h
index 10a46aa6ec..d7a1101c68 100644
--- a/engines/agi/preagi.h
+++ b/engines/agi/preagi.h
@@ -61,6 +61,8 @@ public:
void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
int16 p4, int16 p5, int16 p6, int16 p7) {}
void releaseImageStack() {}
+ int saveGame(const char *fileName, const char *saveName) { return -1; }
+ int loadGame(const char *fileName, bool checkId = true) { return -1; }
// Game
Common::String getTargetName() { return _targetName; }
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 179db94a71..e8fb2522b1 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -28,8 +28,10 @@
* Multi-slots by Claudio Matsuoka <claudio@helllabs.org>
*/
+#include <time.h> // for extended infos
#include "common/file.h"
+#include "graphics/thumbnail.h"
#include "agi/agi.h"
#include "agi/graphics.h"
@@ -37,13 +39,14 @@
#include "agi/keyboard.h"
#include "agi/menu.h"
-#define SAVEGAME_VERSION 3
+#define SAVEGAME_VERSION 4
/*
* Version 0 (Sarien): view table has 64 entries
* Version 1 (Sarien): view table has 256 entries (needed in KQ3)
* Version 2 (ScummVM): first ScummVM version
- * Version 3 (ScummVM): adding AGIPAL save/load support
+ * Version 3 (ScummVM): added AGIPAL save/load support
+ * Version 4 (ScummVM): added thumbnails and save creation date/time
*/
namespace Agi {
@@ -70,6 +73,22 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
out->writeByte(SAVEGAME_VERSION);
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save game version (%d)", SAVEGAME_VERSION);
+ // Thumbnail
+ Graphics::saveThumbnail(*out);
+
+ // Creation date/time
+ tm curTime;
+ _system->getTimeAndDate(curTime);
+
+ uint32 saveDate = (curTime.tm_mday & 0xFF) << 24 | ((curTime.tm_mon + 1) & 0xFF) << 16 | (curTime.tm_year + 1900) & 0xFFFF;
+ uint16 saveTime = (curTime.tm_hour & 0xFF) << 8 | (curTime.tm_min) & 0xFF;
+
+ out->writeUint32BE(saveDate);
+ debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save date (%d)", saveDate);
+ out->writeUint16BE(saveTime);
+ debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save time (%d)", saveTime);
+ // TODO: played time
+
out->writeByte(_game.state);
debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game state (%d)", _game.state);
@@ -250,9 +269,25 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) {
debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Description is: %s", description);
saveVersion = in->readByte();
- if (saveVersion != SAVEGAME_VERSION)
+ if (saveVersion < 2) // is the save game pre-ScummVM?
warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, SAVEGAME_VERSION);
+ if (saveVersion < 3)
+ warning("This save game contains no AGIPAL data, if the game is using the AGIPAL hack, it won't work correctly");
+
+ if (saveVersion >= 4) {
+ // We don't need the thumbnail here, so just read it and discard it
+ Graphics::Surface *thumbnail = new Graphics::Surface();
+ assert(thumbnail);
+ Graphics::loadThumbnail(*in, *thumbnail);
+ delete thumbnail;
+ thumbnail = 0;
+
+ in->readUint32BE(); // save date
+ in->readUint16BE(); // save time
+ // TODO: played time
+ }
+
_game.state = in->readByte();
in->read(loadId, 8);