diff options
| author | Einar Johan Trøan Sømåen | 2012-06-19 02:02:20 +0200 | 
|---|---|---|
| committer | Einar Johan Trøan Sømåen | 2012-06-19 02:02:20 +0200 | 
| commit | 721fd394def5d9930e12f2e7223831e6c2d3bb82 (patch) | |
| tree | 0474004c42c4cc3b873cfb165ecc99f793bc7cc1 | |
| parent | 06e8306aab6458e01b4356b6afa95544c64eae9d (diff) | |
| download | scummvm-rg350-721fd394def5d9930e12f2e7223831e6c2d3bb82.tar.gz scummvm-rg350-721fd394def5d9930e12f2e7223831e6c2d3bb82.tar.bz2 scummvm-rg350-721fd394def5d9930e12f2e7223831e6c2d3bb82.zip | |
WINTERMUTE: Add a first attempt at load-from-launcher support
| -rw-r--r-- | engines/wintermute/Base/BPersistMgr.cpp | 213 | ||||
| -rw-r--r-- | engines/wintermute/Base/BPersistMgr.h | 15 | ||||
| -rw-r--r-- | engines/wintermute/detection.cpp | 51 | ||||
| -rw-r--r-- | engines/wintermute/wintermute.cpp | 8 | 
4 files changed, 231 insertions, 56 deletions
| diff --git a/engines/wintermute/Base/BPersistMgr.cpp b/engines/wintermute/Base/BPersistMgr.cpp index 346a8bfa59..a70b915fc2 100644 --- a/engines/wintermute/Base/BPersistMgr.cpp +++ b/engines/wintermute/Base/BPersistMgr.cpp @@ -36,8 +36,11 @@  #include "engines/wintermute/utils/StringUtil.h"
  #include "engines/wintermute/Base/BImage.h"
  #include "engines/wintermute/Base/BSound.h"
 -#include "commoN/memstream.h"
 +#include "graphics/decoders/bmp.h"
 +#include "common/memstream.h"
  #include "common/str.h"
 +#include "common/system.h"
 +#include "common/savefile.h"
  namespace WinterMute {
 @@ -60,7 +63,7 @@ CBPersistMgr::CBPersistMgr(CBGame *inGame): CBBase(inGame) {  	_richBufferSize = 0;
  	_savedDescription = NULL;
 -	_savedTimestamp = 0;
 +//	_savedTimestamp = 0;
  	_savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
  	_savedExtMajor = _savedExtMinor = 0;
 @@ -91,7 +94,7 @@ void CBPersistMgr::Cleanup() {  	_richBufferSize = 0;
  	_savedDescription = NULL; // ref to buffer
 -	_savedTimestamp = 0;
 +//	_savedTimestamp = 0;
  	_savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
  	_savedExtMajor = _savedExtMinor = 0;
 @@ -114,6 +117,64 @@ uint32 makeUint32(byte first, byte second, byte third, byte fourth) {  	return retVal;
  }
 +Common::String CBPersistMgr::getFilenameForSlot(int slot) {
 +	// TODO: Temporary solution until I have the namespacing sorted out
 +	return Common::String::format("save%03d.DirtySplitSav", slot);
 +}
 +
 +void CBPersistMgr::getSaveStateDesc(int slot, SaveStateDescriptor& desc) {
 +	Common::String filename = getFilenameForSlot(slot);
 +	warning("Trying to list savegame %s in slot %d", filename.c_str(), slot);
 +	if (FAILED(readHeader(filename))) {
 +		warning("getSavedDesc(%d) - Failed for %s", slot, filename.c_str());
 +		return;
 +	}
 +	desc.setSaveSlot(slot);
 +	desc.setDescription(_savedDescription);
 +	desc.setDeletableFlag(true);
 +	desc.setWriteProtectedFlag(false);
 +	
 +	if (_thumbnailDataSize > 0) {
 +		Common::MemoryReadStream thumbStream(_thumbnailData, _thumbnailDataSize);
 +		Graphics::BitmapDecoder bmpDecoder;
 +		if (bmpDecoder.loadStream(thumbStream)) {
 +			Graphics::Surface *surf = new Graphics::Surface;
 +			surf = bmpDecoder.getSurface()->convertTo(g_system->getOverlayFormat());
 +			desc.setThumbnail(surf);
 +		}
 +	}
 +
 +	desc.setSaveDate(_savedTimestamp.tm_year, _savedTimestamp.tm_mon, _savedTimestamp.tm_mday);
 +	desc.setSaveTime(_savedTimestamp.tm_hour, _savedTimestamp.tm_min);
 +	desc.setPlayTime(0);
 +}
 +
 +void CBPersistMgr::deleteSaveSlot(int slot) {
 +	Common::String filename = getFilenameForSlot(slot);
 +	g_system->getSavefileManager()->removeSavefile(filename);
 +}
 +
 +uint32 CBPersistMgr::getMaxUsedSlot() {
 +	Common::StringArray saves = g_system->getSavefileManager()->listSavefiles("save???.DirtySplitSav");
 +	Common::StringArray::iterator it = saves.begin();
 +	int ret = -1;
 +	for (; it != saves.end(); it++) {
 +		int num = -1;
 +		sscanf(it->c_str(), "save%d", &num);
 +		ret = MAX(ret, num);
 +	}
 +	return ret;
 +}
 +
 +bool CBPersistMgr::getSaveExists(int slot) {
 +	Common::String filename = getFilenameForSlot(slot);
 +	warning("Trying to list savegame %s in slot %d", filename.c_str(), slot);
 +	if (FAILED(readHeader(filename))) {
 +		return false;
 +	}
 +	return true;
 +}
 +
  //////////////////////////////////////////////////////////////////////////
  HRESULT CBPersistMgr::InitSave(const char *Desc) {
  	if (!Desc) return E_FAIL;
 @@ -192,11 +253,11 @@ HRESULT CBPersistMgr::InitSave(const char *Desc) {  		PutDWORD(DataOffset);
  		PutString(Desc);
 -// TODO: Add usefull timestamps, we can't use ctime...
 -/*		time_t Timestamp;
 -		time(&Timestamp);
 -		PutDWORD((uint32)Timestamp);*/
 -		PutDWORD(0);
 +
 +		g_system->getTimeAndDate(_savedTimestamp);
 +		putTimeDate(_savedTimestamp);
 +		_savedPlayTime = g_system->getMillis();
 +		_saveStream->writeUint32LE(_savedPlayTime);
  	}
  	return S_OK;
  }
 @@ -224,18 +285,21 @@ uint16 getHighWord(uint32 dword) {  	return dword >> 16;
  }
 -//////////////////////////////////////////////////////////////////////////
 -HRESULT CBPersistMgr::InitLoad(const char *Filename) {
 +HRESULT CBPersistMgr::readHeader(const Common::String &filename) {
  	Cleanup();
 -
 +	
  	_saving = false;
 -
 -	_loadStream = Game->_fileManager->loadSaveGame(Filename);
 +	
 +	_loadStream = g_system->getSavefileManager()->openForLoading(filename);
  	//_buffer = Game->_fileManager->ReadWholeFile(Filename, &_bufferSize);
  	if (_loadStream) {
  		uint32 Magic;
  		Magic = GetDWORD();
 -		if (Magic != DCGF_MAGIC) goto init_fail;
 +
 +		if (Magic != DCGF_MAGIC) {
 +			Cleanup();
 +			return E_FAIL;
 +		}
  		Magic = GetDWORD();
 @@ -244,14 +308,10 @@ HRESULT CBPersistMgr::InitLoad(const char *Filename) {  			_savedVerMinor = _loadStream->readByte();
  			_savedExtMajor = _loadStream->readByte();
  			_savedExtMinor = _loadStream->readByte();
 -
 +			
  			if (Magic == SAVE_MAGIC_2) {
  				_savedVerBuild = (byte)GetDWORD();
 -				char *SavedName = GetString();
 -				if (SavedName == NULL || scumm_stricmp(SavedName, Game->_name) != 0) {
 -					Game->LOG(0, "ERROR: Saved game name doesn't match current game");
 -					goto init_fail;
 -				}
 +				_savedName = GetString();
  				// load thumbnail
  				_thumbnailDataSize = GetDWORD();
 @@ -263,48 +323,68 @@ HRESULT CBPersistMgr::InitLoad(const char *Filename) {  				}
  			} else _savedVerBuild = 35; // last build with ver1 savegames
 +			uint32 DataOffset = GetDWORD();
 -			// if save is newer version than we are, fail
 -			if (_savedVerMajor >  DCGF_VER_MAJOR ||
 -			        (_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor >  DCGF_VER_MINOR) ||
 -			        (_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor == DCGF_VER_MINOR && _savedVerBuild > DCGF_VER_BUILD)
 -			   ) {
 -				Game->LOG(0, "ERROR: Saved game version is newer than current game");
 -				goto init_fail;
 -			}
 +			_savedDescription = GetString();
 +			_savedTimestamp = getTimeDate();
 +			_savedPlayTime = _loadStream->readUint32LE();
 -			// if save is older than the minimal version we support
 -			if (_savedVerMajor <  SAVEGAME_VER_MAJOR ||
 -			        (_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor <  SAVEGAME_VER_MINOR) ||
 -			        (_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor == SAVEGAME_VER_MINOR && _savedVerBuild < SAVEGAME_VER_BUILD)
 -			   ) {
 -				Game->LOG(0, "ERROR: Saved game is too old and cannot be used by this version of game engine");
 -				goto init_fail;
 -			}
 +			_offset = DataOffset;
 +			
 +			return S_OK;
 +		}
 +	}
 -			/*
 -			if ( _savedVerMajor != DCGF_VER_MAJOR || _savedVerMinor != DCGF_VER_MINOR)
 -			{
 -			    Game->LOG(0, "ERROR: Saved game is created by other WME version");
 -			    goto init_fail;
 -			}
 -			*/
 -		} else goto init_fail;
 +	Cleanup();
 +	return E_FAIL;
 +}
 +//////////////////////////////////////////////////////////////////////////
 +HRESULT CBPersistMgr::InitLoad(const char *Filename) {
 -		uint32 DataOffset = GetDWORD();
 -		_savedDescription = GetString();
 -		_savedTimestamp = (time_t)GetDWORD();
 +	if (FAILED(readHeader(Filename))) {
 +		Cleanup();
 +		return E_FAIL;
 +	}
 +	_saving = false;
 -		_offset = DataOffset;
 +	if (_savedName == "" || scumm_stricmp(_savedName.c_str(), Game->_name) != 0) {
 +		Game->LOG(0, "ERROR: Saved game name doesn't match current game");
 +		Cleanup();
 +		return E_FAIL;
 +	}
 -		return S_OK;
 +	// if save is newer version than we are, fail
 +	if (_savedVerMajor >  DCGF_VER_MAJOR ||
 +		(_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor >  DCGF_VER_MINOR) ||
 +		(_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor == DCGF_VER_MINOR && _savedVerBuild > DCGF_VER_BUILD)
 +		) {
 +		Game->LOG(0, "ERROR: Saved game version is newer than current game");
 +		Cleanup();
 +		return E_FAIL;
  	}
 -init_fail:
 -	Cleanup();
 -	return E_FAIL;
 +	// if save is older than the minimal version we support
 +	if (_savedVerMajor <  SAVEGAME_VER_MAJOR ||
 +		(_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor <  SAVEGAME_VER_MINOR) ||
 +		(_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor == SAVEGAME_VER_MINOR && _savedVerBuild < SAVEGAME_VER_BUILD)
 +		) {
 +		Game->LOG(0, "ERROR: Saved game is too old and cannot be used by this version of game engine");
 +		Cleanup();
 +		return E_FAIL;
 +
 +	}
 +
 +	/*
 +	 if ( _savedVerMajor != DCGF_VER_MAJOR || _savedVerMinor != DCGF_VER_MINOR)
 +	 {
 +	 Game->LOG(0, "ERROR: Saved game is created by other WME version");
 +	 goto init_fail;
 +	 }
 +	 */
 +
 +	return S_OK;
  }
 @@ -387,13 +467,40 @@ char *CBPersistMgr::GetString() {  	ret[len] = '\0';
  /*	char *ret = (char *)(_buffer + _offset);
  	_offset += len;*/
 -
 +	warning("Read string %s with len %d", ret, len);
  	if (!strcmp(ret, "(null)")) { 
  		delete[] ret;
  		return NULL;
  	} else return ret;
  }
 +HRESULT CBPersistMgr::putTimeDate(const TimeDate &t) {
 +	_saveStream->writeSint32LE(t.tm_sec);
 +	_saveStream->writeSint32LE(t.tm_min);
 +	_saveStream->writeSint32LE(t.tm_hour);
 +	_saveStream->writeSint32LE(t.tm_mday);
 +	_saveStream->writeSint32LE(t.tm_mon);
 +	_saveStream->writeSint32LE(t.tm_year);
 +	// _saveStream->writeSint32LE(t.tm_wday); //TODO: Add this in when merging next
 +	
 +	if (_saveStream->err()) {
 +		return E_FAIL;
 +	}
 +	return S_OK;
 +}
 +
 +TimeDate CBPersistMgr::getTimeDate() {
 +	TimeDate t;
 +	t.tm_sec = _loadStream->readSint32LE();
 +	t.tm_min = _loadStream->readSint32LE();
 +	t.tm_hour = _loadStream->readSint32LE();
 +	t.tm_mday = _loadStream->readSint32LE();
 +	t.tm_mon = _loadStream->readSint32LE();
 +	t.tm_year = _loadStream->readSint32LE();
 +	// t.tm_wday = _loadStream->readSint32LE(); //TODO: Add this in when merging next
 +	return t;
 +}
 +
  void CBPersistMgr::putFloat(float val) {
  	Common::String str = Common::String::format("F%f", val);
  	_saveStream->writeUint32LE(str.size());
 diff --git a/engines/wintermute/Base/BPersistMgr.h b/engines/wintermute/Base/BPersistMgr.h index 0fe1d75550..12760bf6ca 100644 --- a/engines/wintermute/Base/BPersistMgr.h +++ b/engines/wintermute/Base/BPersistMgr.h @@ -31,7 +31,10 @@  #include "engines/wintermute/Base/BBase.h"
 +#include "engines/savestate.h"
  #include "common/stream.h"
 +#include "common/str.h"
 +#include "common/system.h"
  namespace WinterMute {
 @@ -40,12 +43,14 @@ class Vector2;  class CBPersistMgr : public CBBase {
  public:
  	char *_savedDescription;
 -	time_t _savedTimestamp;
 +	TimeDate _savedTimestamp;
 +	uint32 _savedPlayTime;
  	byte _savedVerMajor;
  	byte _savedVerMinor;
  	byte _savedVerBuild;
  	byte _savedExtMajor;
  	byte _savedExtMinor;
 +	Common::String _savedName;
  	HRESULT SaveFile(const char *Filename);
  	uint32 GetDWORD();
  	void PutDWORD(uint32 Val);
 @@ -56,6 +61,10 @@ public:  	double getDouble();
  	void putDouble(double val);
  	void Cleanup();
 +	void getSaveStateDesc(int slot, SaveStateDescriptor& desc);
 +	void deleteSaveSlot(int slot);
 +	uint32 getMaxUsedSlot();
 +	bool getSaveExists(int slot);
  	HRESULT InitLoad(const char *Filename);
  	HRESULT InitSave(const char *Desc);
  	HRESULT GetBytes(byte  *Buffer, uint32 Size);
 @@ -89,6 +98,10 @@ public:  	uint32 _thumbnailDataSize;
  	byte *_thumbnailData;
  private:
 +	Common::String getFilenameForSlot(int slot);
 +	HRESULT readHeader(const Common::String &filename);
 +	TimeDate getTimeDate();
 +	HRESULT putTimeDate(const TimeDate &t);
  	Common::WriteStream *_saveStream;
  	Common::SeekableReadStream *_loadStream;
  };
 diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 4756c96542..610f34c643 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -22,6 +22,7 @@  #include "engines/advancedDetector.h"  #include "engines/wintermute/wintermute.h" +#include "engines/wintermute/Base/BPersistMgr.h"  #include "common/config-manager.h"  #include "common/error.h" @@ -179,6 +180,56 @@ public:  		// Failed to find any game data  		return false;  	} + +	bool hasFeature(MetaEngineFeature f) const { +		switch (f) { +			case MetaEngine::kSupportsListSaves: +				return true; +			case MetaEngine::kSupportsLoadingDuringStartup: +				return true; +			case MetaEngine::kSupportsDeleteSave: +				return true; +			case MetaEngine::kSavesSupportCreationDate: +				return true; +			case MetaEngine::kSavesSupportMetaInfo:			 +				return true; +			case MetaEngine::kSavesSupportThumbnail:			 +				return true; +			default: +				return false; +		} +	} + +	SaveStateList listSaves(const char *target) const { +		SaveStateList saves; +		WinterMute::CBPersistMgr pm; +		for (int i = 0; i < getMaximumSaveSlot(); i++) { +			if (pm.getSaveExists(i)) { +				SaveStateDescriptor desc; +				pm.getSaveStateDesc(i, desc); +				saves.push_back(desc); +			} +		} +		return saves; +	} +	 +	int getMaximumSaveSlot() const { +		WinterMute::CBPersistMgr pm; +		return pm.getMaxUsedSlot() + 1; // TODO: Since we use slot 0, this misses a bit. +	} +	 +	void removeSaveState(const char *target, int slot) const { +		WinterMute::CBPersistMgr pm; +		pm.deleteSaveSlot(slot); +	} +	 +	virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const { +		WinterMute::CBPersistMgr pm; +		SaveStateDescriptor retVal; +		retVal.setDescription("Invalid savegame"); +		pm.getSaveStateDesc(slot, retVal); +		return retVal; +	}  };  #if PLUGIN_ENABLED_DYNAMIC(WINTERMUTE) diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index 8b12a422cf..4e24d740b9 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -130,6 +130,7 @@ int WinterMuteEngine::init() {  	int argc = 0;  	_game = new CAdGame;  	if (!_game) return 1; +	CBPlatform::Initialize(_game, 0, NULL);  	bool windowedMode = true; @@ -234,14 +235,17 @@ int WinterMuteEngine::init() {  	_game->LOG(0, "Engine initialized in %d ms", CBPlatform::GetTime() - DataInitStart);  	_game->LOG(0, ""); +	if (ConfMan.hasKey("save_slot")) { +		int slot = ConfMan.getInt("save_slot"); +		Common::String str = Common::String::format("save00%d.DirtySplitSav", slot); +		_game->LoadGame(str.c_str()); +	}  	if (SaveGame) {  		_game->LoadGame(SaveGame);  		delete [] SaveGame;  	} -	CBPlatform::Initialize(_game, 0, NULL); -	  	// all set, ready to go  	return 0;  } | 
