diff options
| -rw-r--r-- | engines/agi/agi.h | 6 | ||||
| -rw-r--r-- | engines/agi/detection.cpp | 104 | ||||
| -rw-r--r-- | engines/agi/preagi.h | 2 | ||||
| -rw-r--r-- | engines/agi/saveload.cpp | 41 | 
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); | 
