diff options
Diffstat (limited to 'engines')
| -rw-r--r-- | engines/xeen/detection.cpp | 4 | ||||
| -rw-r--r-- | engines/xeen/files.cpp | 139 | ||||
| -rw-r--r-- | engines/xeen/files.h | 93 | ||||
| -rw-r--r-- | engines/xeen/items.h | 34 | ||||
| -rw-r--r-- | engines/xeen/map.cpp | 12 | ||||
| -rw-r--r-- | engines/xeen/party.cpp | 12 | ||||
| -rw-r--r-- | engines/xeen/party.h | 1 | ||||
| -rw-r--r-- | engines/xeen/saves.cpp | 247 | ||||
| -rw-r--r-- | engines/xeen/saves.h | 74 | ||||
| -rw-r--r-- | engines/xeen/spells.cpp | 2 | ||||
| -rw-r--r-- | engines/xeen/xeen.cpp | 124 | ||||
| -rw-r--r-- | engines/xeen/xeen.h | 22 | 
12 files changed, 395 insertions, 369 deletions
diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp index 0866d5f107..df3df4ffa7 100644 --- a/engines/xeen/detection.cpp +++ b/engines/xeen/detection.cpp @@ -144,7 +144,7 @@ SaveStateList XeenMetaEngine::listSaves(const char *target) const {  			Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);  			if (in) { -				Xeen::XeenEngine::readSavegameHeader(in, header); +				Xeen::SavesManager::readSavegameHeader(in, header);  				saveList.push_back(SaveStateDescriptor(slot, header._saveName));  				header._thumbnail->free(); @@ -172,7 +172,7 @@ SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int s  	if (f) {  		Xeen::XeenSavegameHeader header; -		Xeen::XeenEngine::readSavegameHeader(f, header); +		Xeen::SavesManager::readSavegameHeader(f, header);  		delete f;  		// Create the return descriptor diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index b62a0d8cd5..d63c63d651 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -186,8 +186,6 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S  FileManager::FileManager(XeenEngine *vm) {  	Common::File f; -	int sideNum = 0; -  	_isDarkCc = vm->getGameID() == GType_DarkSide;  	File::_xeenCc = (vm->getGameID() == GType_DarkSide) ? nullptr : @@ -220,9 +218,12 @@ void FileManager::setGameCc(int ccMode) {  /*------------------------------------------------------------------------*/ -CCArchive *File::_currentArchive;  CCArchive *File::_xeenCc;  CCArchive *File::_darkCc; +SaveArchive *File::_xeenSave; +SaveArchive *File::_darkSave; +BaseCCArchive *File::_currentArchive; +SaveArchive *File::_currentSave;  File::File(const Common::String &filename) {  	File::open(filename); @@ -237,7 +238,7 @@ File::File(const Common::String &filename, int ccMode) {  }  bool File::open(const Common::String &filename) { -	if (!g_vm->_saves || !Common::File::open(filename, *g_vm->_saves)) { +	if (!_currentSave || !Common::File::open(filename, *_currentSave)) {  		if (!Common::File::open(filename, *_currentArchive)) {  			// Could not find in current archive, so try intro.cc or in folder  			if (!Common::File::open(filename)) @@ -269,10 +270,12 @@ void File::setCurrentArchive(int ccMode) {  	switch (ccMode) {  	case 0:  		_currentArchive = _xeenCc; +		_currentSave = _xeenSave;  		break;  	case 1:  		_currentArchive = _darkCc; +		_currentSave = _darkSave;  		break;  	default: @@ -293,7 +296,7 @@ Common::String File::readString() {  }  bool File::exists(const Common::String &filename) { -	if (!g_vm->_saves || !g_vm->_saves->hasFile(filename)) { +	if (!_currentSave || !_currentSave->hasFile(filename)) {  		if (!_currentArchive->hasFile(filename)) {  			// Could not find in current archive, so try intro.cc or in folder  			return Common::File::exists(filename); @@ -314,6 +317,28 @@ bool File::exists(const Common::String &filename, int ccMode) {  	return result;  } +void File::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) { +	byte data = 0; + +	int bitCounter = 0; +	for (bool *p = startP; p <= endP; ++p, bitCounter = (bitCounter + 1) % 8) { +		if (p == endP || bitCounter == 0) { +			if (p != endP || s.isSaving()) +				s.syncAsByte(data); +			if (p == endP) +				break; + +			if (s.isSaving()) +				data = 0; +		} + +		if (s.isLoading()) +			*p = (data >> bitCounter) != 0; +		else if (*p) +			data |= 1 << bitCounter; +	} +} +  /*------------------------------------------------------------------------*/  void StringArray::load(const Common::String &name) { @@ -330,4 +355,108 @@ void StringArray::load(const Common::String &name, int ccMode) {  		push_back(f.readString());  } +/*------------------------------------------------------------------------*/ + +SaveArchive::SaveArchive(Party *party) : BaseCCArchive(), _party(party) { +	_data = nullptr; +} + +SaveArchive::~SaveArchive() { +	for (Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *>::iterator it = _newData.begin(); it != _newData.end(); it++) { +		delete (*it)._value; +	} +	delete[] _data; +} + +Common::SeekableReadStream *SaveArchive::createReadStreamForMember(const Common::String &name) const { +	CCEntry ccEntry; + +	// If the given resource has already been perviously "written" to the +	// save manager, then return that new resource +	uint16 id = BaseCCArchive::convertNameToId(name); +	if (_newData.contains(id)) { +		Common::MemoryWriteStreamDynamic *stream = _newData[id]; +		return new Common::MemoryReadStream(stream->getData(), stream->size()); +	} + +	// Retrieve the resource from the loaded savefile +	if (getHeaderEntry(name, ccEntry)) { +		// Open the correct CC entry +		return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); +	} + +	return nullptr; +} + +void SaveArchive::load(Common::SeekableReadStream *stream) { +	loadIndex(stream); + +	delete[] _data; +	_data = new byte[stream->size()]; +	stream->seek(0); +	stream->read(_data, stream->size()); + +	// Load in the character stats and active party +	Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr"); +	Common::Serializer sChr(chr, nullptr); +	_party->_roster.synchronize(sChr); +	delete chr; + +	Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty"); +	Common::Serializer sPty(pty, nullptr); +	_party->synchronize(sPty); +	delete pty; +} + +void SaveArchive::reset(CCArchive *src) { +	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); +	File fIn; + +	g_vm->_files->setGameCc(g_vm->getGameID() == GType_DarkSide ? 1 : 0); +	const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C }; +	for (int i = 0; i < 6; ++i) { +		Common::String filename = Common::String::format("%.4x", RESOURCES[i]); +		if (src->hasFile(filename)) { +			// Read in the next resource +			fIn.open(filename, *src); +			byte *data = new byte[fIn.size()]; +			fIn.read(data, fIn.size()); + +			// Copy it to the combined savefile resource +			saveFile.write(data, fIn.size()); +			delete[] data; +			fIn.close(); +		} +	} + +	assert(saveFile.size() > 0); +	Common::MemoryReadStream f(saveFile.getData(), saveFile.size()); +	load(&f); +} + +/*------------------------------------------------------------------------*/ + +OutFile::OutFile(const Common::String filename) : +		_filename(filename), _backingStream(DisposeAfterUse::YES) { +	_archive = File::_currentSave; +} + +uint32 OutFile::write(const void *dataPtr, uint32 dataSize) { +	return _backingStream.write(dataPtr, dataSize); +} + +int32 OutFile::pos() const { +	return _backingStream.pos(); +} + +void OutFile::finalize() { +	uint16 id = BaseCCArchive::convertNameToId(_filename); + +	if (!_archive->_newData.contains(id)) +		_archive->_newData[id] = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); + +	Common::MemoryWriteStreamDynamic *out = _archive->_newData[id]; +	out->write(_backingStream.getData(), _backingStream.size()); +} +  } // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 1fcfa6a7b8..f18d23671a 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -26,6 +26,8 @@  #include "common/scummsys.h"  #include "common/array.h"  #include "common/file.h" +#include "common/memstream.h" +#include "common/savefile.h"  #include "common/serializer.h"  #include "common/str-array.h"  #include "graphics/surface.h" @@ -34,7 +36,12 @@ namespace Xeen {  class XeenEngine;  class CCArchive; +class BaseCCArchive;  class File; +class SaveArchive; +class Party; +class OutFile; +class SavesManager;  #define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \  	template<typename T> \ @@ -50,6 +57,20 @@ class File;  		_bytesSynced += SIZE; \  	} +/** + * Details of a single entry in a CC file index + */ +struct CCEntry { +	uint16 _id; +	uint32 _offset; +	uint16 _size; + +	CCEntry() : _id(0), _offset(0), _size(0) {} +	CCEntry(uint16 id, uint32 offset, uint32 size) +		: _id(id), _offset(offset), _size(size) { +	} +}; +  /*   * Main resource manager   */ @@ -79,15 +100,23 @@ public:   */  class File : public Common::File {  	friend class FileManager; +	friend class OutFile; +	friend class SavesManager;  private: -	static CCArchive *_currentArchive; -	static CCArchive *_xeenCc; -	static CCArchive *_darkCc; +	static CCArchive *_xeenCc, *_darkCc; +	static SaveArchive *_xeenSave, *_darkSave; +	static BaseCCArchive *_currentArchive; +	static SaveArchive *_currentSave;  public:  	/**  	 * Sets which archive is used by default  	 */  	static void setCurrentArchive(int ccMode); + +	/** +	 * Synchronizes a boolean array as a bitfield set +	 */ +	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP);  public:  	File() : Common::File() {}  	File(const Common::String &filename); @@ -175,22 +204,8 @@ public:  };  /** -* Details of a single entry in a CC file index -*/ -struct CCEntry { -	uint16 _id; -	uint32 _offset; -	uint16 _size; - -	CCEntry() : _id(0), _offset(0), _size(0) {} -	CCEntry(uint16 id, uint32 offset, uint32 size) -		: _id(id), _offset(offset), _size(size) { -	} -}; - -/** -* Base Xeen CC file implementation -*/ + * Base Xeen CC file implementation + */  class BaseCCArchive : public Common::Archive {  protected:  	Common::Array<CCEntry> _index; @@ -220,8 +235,8 @@ public:  };  /** -* Xeen CC file implementation -*/ + * Xeen CC file implementation + */  class CCArchive : public BaseCCArchive {  private:  	Common::String _filename; @@ -238,6 +253,42 @@ public:  	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;  }; +class SaveArchive : public BaseCCArchive { +	friend class OutFile; +private: +	Party *_party; +	byte *_data; +	Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *> _newData; + +	void load(Common::SeekableReadStream *stream); +public: +	SaveArchive(Party *party); +	~SaveArchive(); + +	/** +	* Sets up the dynamic data for the game for a new game +	*/ +	void reset(CCArchive *src); + +	// Archive implementation +	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +class OutFile : public Common::WriteStream { +private: +	SaveArchive *_archive; +	Common::String _filename; +	Common::MemoryWriteStreamDynamic _backingStream; +public: +	OutFile(const Common::String filename); + +	void finalize(); + +	uint32 write(const void *dataPtr, uint32 dataSize) override; + +	int32 pos() const override; +}; +  } // End of namespace Xeen  #endif /* XEEN_FILES_H */ diff --git a/engines/xeen/items.h b/engines/xeen/items.h deleted file mode 100644 index bfbd9e4481..0000000000 --- a/engines/xeen/items.h +++ /dev/null @@ -1,34 +0,0 @@ -/* 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 XEEN_ITEMS_H -#define XEEN_ITEMS_H - -#include "xeen/character.h" - -namespace Xeen { - - - -} // End of namespace Xeen - -#endif	/* XEEN_ITEMS_H */ diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 6777178d31..6a442be247 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -620,9 +620,9 @@ void MazeData::synchronize(Common::SeekableReadStream &s) {  	Common::Serializer ser(&s, nullptr);  	for (int y = 0; y < MAP_HEIGHT; ++y) -		SavesManager::syncBitFlags(ser, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]); +		File::syncBitFlags(ser, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]);  	for (int y = 0; y < MAP_HEIGHT; ++y) -		SavesManager::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]); +		File::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]);  }  void MazeData::setAllTilesStepped() { @@ -1115,7 +1115,7 @@ void Map::load(int mapId) {  	mapId = party._mazeId;  	Common::String filename = Common::String::format("maze%c%03d.mob",  		(mapId >= 100) ? 'x' : '0', mapId); -	File mobFile(filename, *_vm->_saves); +	File mobFile(filename);  	XeenSerializer sMob(&mobFile, nullptr);  	_mobData.synchronize(sMob, _monsterData);  	mobFile.close(); @@ -1395,7 +1395,7 @@ void Map::loadEvents(int mapId) {  	// Load events  	Common::String filename = Common::String::format("maze%c%03d.evt",  		(mapId >= 100) ? 'x' : '0', mapId); -	File fEvents(filename, *_vm->_saves); +	File fEvents(filename);  	XeenSerializer sEvents(&fEvents, nullptr);  	_events.synchronize(sEvents);  	fEvents.close(); @@ -1418,7 +1418,7 @@ void Map::saveMaze() {  	// Save the event data  	Common::String filename = Common::String::format("maze%c%03d.evt",  		(mazeNum >= 100) ? 'x' : '0', mazeNum); -	OutFile fEvents(_vm, filename); +	OutFile fEvents(filename);  	XeenSerializer sEvents(nullptr, &fEvents);  	_events.synchronize(sEvents);  	fEvents.finalize(); @@ -1426,7 +1426,7 @@ void Map::saveMaze() {  	// Save the maze MOB file  	filename = Common::String::format("maze%c%03d.mob",  		(mazeNum >= 100) ? 'x' : '0', mazeNum); -	OutFile fMob(_vm, filename); +	OutFile fMob(filename);  	XeenSerializer sMob(nullptr, &fEvents);  	_mobData.synchronize(sMob, _monsterData);  	fEvents.finalize(); diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index abedaa46ed..0a2e5b9f82 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -206,11 +206,11 @@ void Party::synchronize(Common::Serializer &s) {  	s.syncAsUint32LE(_bankGems);  	s.syncAsUint32LE(_totalTime);  	s.syncAsByte(_rested); -	SavesManager::syncBitFlags(s, &_gameFlags[0][0], &_gameFlags[0][256]); -	SavesManager::syncBitFlags(s, &_gameFlags[1][0], &_gameFlags[1][256]); -	SavesManager::syncBitFlags(s, &_worldFlags[0], &_worldFlags[128]); -	SavesManager::syncBitFlags(s, &_questFlags[0][0], &_questFlags[0][30]); -	SavesManager::syncBitFlags(s, &_questFlags[1][0], &_questFlags[1][30]); +	File::syncBitFlags(s, &_gameFlags[0][0], &_gameFlags[0][256]); +	File::syncBitFlags(s, &_gameFlags[1][0], &_gameFlags[1][256]); +	File::syncBitFlags(s, &_worldFlags[0], &_worldFlags[128]); +	File::syncBitFlags(s, &_questFlags[0][0], &_questFlags[0][30]); +	File::syncBitFlags(s, &_questFlags[1][0], &_questFlags[1][30]);  	for (int i = 0; i < 85; ++i)  		s.syncAsByte(_questItems[i]); @@ -225,7 +225,7 @@ void Party::synchronize(Common::Serializer &s) {  		_blacksmithMisc[1][i].synchronize(s);  	for (int i = 0; i < TOTAL_CHARACTERS; ++i) -		SavesManager::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]); +		File::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);  	s.syncBytes(&dummy[0], 30);  } diff --git a/engines/xeen/party.h b/engines/xeen/party.h index f6df5ff83e..31feaec503 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -30,7 +30,6 @@  #include "xeen/character.h"  #include "xeen/combat.h"  #include "xeen/dialogs_error.h" -#include "xeen/items.h"  namespace Xeen { diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 5126642df1..504bb18dd7 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -23,155 +23,176 @@  #include "common/scummsys.h"  #include "common/algorithm.h"  #include "common/memstream.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h"  #include "xeen/saves.h"  #include "xeen/files.h"  #include "xeen/xeen.h"  namespace Xeen { -OutFile::OutFile(XeenEngine *vm, const Common::String filename) : -		_vm(vm), -		_filename(filename), -		_backingStream(DisposeAfterUse::YES) { -} +SavesManager::SavesManager(const Common::String &targetName): _targetName(targetName), +		_wonWorld(false), _wonDarkSide(false) { +	File::_xeenSave = nullptr; +	File::_darkSave = nullptr; -uint32 OutFile::write(const void *dataPtr, uint32 dataSize) { -	return _backingStream.write(dataPtr, dataSize); -} +	if (g_vm->getGameID() != GType_Clouds) { +		File::_darkSave = new SaveArchive(g_vm->_party); +		File::_darkSave->reset(File::_darkCc); +	} +	if (g_vm->getGameID() != GType_DarkSide) { +		File::_xeenSave = new SaveArchive(g_vm->_party); +		File::_xeenSave->reset(File::_xeenCc); +	} -int32 OutFile::pos() const { -	return _backingStream.pos(); -} +	File::_currentSave = g_vm->getGameID() == GType_DarkSide ? +		File::_darkSave : File::_xeenSave; +	assert(File::_currentSave); -void OutFile::finalize() { -	uint16 id = BaseCCArchive::convertNameToId(_filename); +	// Set any final initial values +	Party &party = *g_vm->_party; +	party.resetBlacksmithWares(); +	party._year = g_vm->getGameID() == GType_WorldOfXeen ? 610 : 850; +	party._totalTime = 0; +} -	if (!_vm->_saves->_newData.contains(id)) -		_vm->_saves->_newData[id] = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); +SavesManager::~SavesManager() { +	delete File::_xeenSave; +	delete File::_darkSave; +} -	Common::MemoryWriteStreamDynamic *out = _vm->_saves->_newData[id]; -	out->write(_backingStream.getData(), _backingStream.size()); +void SavesManager::readCharFile() { +	warning("TODO: readCharFile");  } -/*------------------------------------------------------------------------*/ +void SavesManager::writeCharFile() { +	warning("TODO: writeCharFile"); +} -SavesManager::SavesManager(XeenEngine *vm, Party &party) : -		BaseCCArchive(), _vm(vm), _party(party) { -	_data = nullptr; -	_wonWorld = false; -	_wonDarkSide = false; +void SavesManager::saveChars() { +	warning("TODO: saveChars");  } -SavesManager::~SavesManager() { -	for (Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *>::iterator it = _newData.begin(); it != _newData.end(); it++) { -		delete (*it)._value; -	} -	delete[] _data; +const char *const SAVEGAME_STR = "XEEN"; +#define SAVEGAME_STR_SIZE 6 + +bool SavesManager::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header) { +	char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; +	header._thumbnail = nullptr; + +	// Validate the header Id +	in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); +	if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) +		return false; + +	header._version = in->readByte(); +	if (header._version > XEEN_SAVEGAME_VERSION) +		return false; + +	// Read in the string +	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._year = in->readSint16LE(); +	header._month = in->readSint16LE(); +	header._day = in->readSint16LE(); +	header._hour = in->readSint16LE(); +	header._minute = in->readSint16LE(); +	header._totalFrames = in->readUint32LE(); + +	return true;  } -void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) { -	byte data = 0; - -	int bitCounter = 0; -	for (bool *p = startP; p <= endP; ++p, bitCounter = (bitCounter + 1) % 8) { -		if (p == endP || bitCounter == 0) { -			if (p != endP || s.isSaving()) -				s.syncAsByte(data); -			if (p == endP) -				break; - -			if (s.isSaving()) -				data = 0; -		} - -		if (s.isLoading()) -			*p = (data >> bitCounter) != 0; -		else if (*p) -			data |= 1 << bitCounter; -	} +void SavesManager::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header) { +	// Write out a savegame header +	out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + +	out->writeByte(XEEN_SAVEGAME_VERSION); + +	// Write savegame name +	out->writeString(header._saveName); +	out->writeByte('\0'); + +	// Write a thumbnail of the screen +	/* +	uint8 thumbPalette[768]; +	_screen->getPalette(thumbPalette); +	Graphics::Surface saveThumb; +	::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(), +	_screen->w, _screen->h, thumbPalette); +	Graphics::saveThumbnail(*out, saveThumb); +	saveThumb.free(); +	*/ +	// Write out the save date/time +	TimeDate td; +	g_system->getTimeAndDate(td); +	out->writeSint16LE(td.tm_year + 1900); +	out->writeSint16LE(td.tm_mon + 1); +	out->writeSint16LE(td.tm_mday); +	out->writeSint16LE(td.tm_hour); +	out->writeSint16LE(td.tm_min); +	//	out->writeUint32LE(_events->getFrameCounter());  } -Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const { -	CCEntry ccEntry; +Common::Error SavesManager::saveGameState(int slot, const Common::String &desc) { +	Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( +		generateSaveName(slot)); +	if (!out) +		return Common::kCreatingFileFailed; -	// If the given resource has already been perviously "written" to the -	// save manager, then return that new resource -	uint16 id = BaseCCArchive::convertNameToId(name); -	if (_newData.contains(id)) { -		Common::MemoryWriteStreamDynamic *stream = _newData[id]; -		return new Common::MemoryReadStream(stream->getData(), stream->size()); -	} +	XeenSavegameHeader header; +	header._saveName = desc; +	writeSavegameHeader(out, header); -	// Retrieve the resource from the loaded savefile -	if (getHeaderEntry(name, ccEntry)) { -		// Open the correct CC entry -		return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); -	} +	Common::Serializer s(nullptr, out); +	synchronize(s); -	return nullptr; -} +	out->finalize(); +	delete out; -void SavesManager::load(Common::SeekableReadStream *stream) { -	loadIndex(stream); +	return Common::kNoError; +} -	delete[] _data; -	_data = new byte[stream->size()]; -	stream->seek(0); -	stream->read(_data, stream->size()); +Common::Error SavesManager::loadGameState(int slot) { +	Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( +		generateSaveName(slot)); +	if (!saveFile) +		return Common::kReadingFailed; -	// Load in the character stats and active party -	Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr"); -	Common::Serializer sChr(chr, nullptr); -	_party._roster.synchronize(sChr); -	delete chr; +	Common::Serializer s(saveFile, nullptr); -	Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty"); -	Common::Serializer sPty(pty, nullptr); -	_party.synchronize(sPty); -	delete pty; -} +	// Load the savaegame header +	XeenSavegameHeader header; +	if (!readSavegameHeader(saveFile, header)) +		error("Invalid savegame"); -void SavesManager::reset() { -	Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES); -	File fIn; - -	g_vm->_files->setGameCc(g_vm->getGameID() == GType_DarkSide ? 1 : 0); -	const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C }; -	for (int i = 0; i < 6; ++i) { -		Common::String filename = Common::String::format("%.4x", RESOURCES[i]); -		if (fIn.exists(filename)) { -			// Read in the next resource -			fIn.open(filename); -			byte *data = new byte[fIn.size()]; -			fIn.read(data, fIn.size()); - -			// Copy it to the combined savefile resource -			saveFile.write(data, fIn.size()); -			delete[] data; -			fIn.close(); -		} +	if (header._thumbnail) { +		header._thumbnail->free(); +		delete header._thumbnail;  	} -	assert(saveFile.size() > 0); -	Common::MemoryReadStream f(saveFile.getData(), saveFile.size()); -	load(&f); +	// Load most of the savegame data +	synchronize(s); +	delete saveFile; -	// Set any final initial values -	_party.resetBlacksmithWares(); -	_party._year = _vm->getGameID() == GType_WorldOfXeen ? 610 : 850; -	_party._totalTime = 0; +	return Common::kNoError;  } -void SavesManager::readCharFile() { -	warning("TODO: readCharFile"); +Common::String SavesManager::generateSaveName(int slot) { +	return Common::String::format("%s.%03d", _targetName.c_str(), slot);  } -void SavesManager::writeCharFile() { -	warning("TODO: writeCharFile"); +void SavesManager::synchronize(Common::Serializer &s) { +	// TODO  } -void SavesManager::saveChars() { -	warning("TODO: saveChars"); -}  } // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 9c161c838c..2711cc7f2c 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -24,11 +24,11 @@  #define XEEN_SAVES_H  #include "common/scummsys.h" -#include "common/memstream.h"  #include "common/savefile.h" +#include "common/serializer.h" +#include "common/str.h"  #include "graphics/surface.h"  #include "xeen/party.h" -#include "xeen/files.h"  namespace Xeen { @@ -41,59 +41,57 @@ struct XeenSavegameHeader {  	int _totalFrames;  }; -class XeenEngine; -class SavesManager; - -class OutFile : public Common::WriteStream { +class SavesManager {  private: -	XeenEngine *_vm; -	Common::String _filename; -	Common::MemoryWriteStreamDynamic _backingStream; -public: -	OutFile(XeenEngine *vm, const Common::String filename); - -	void finalize(); - -	uint32 write(const void *dataPtr, uint32 dataSize) override; - -	int32 pos() const override; -}; - -class SavesManager: public BaseCCArchive { -	friend class OutFile; +	Common::String _targetName;  private: -	XeenEngine *_vm; -	Party &_party; -	byte *_data; -	Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *> _newData; +	/** +	 * Synchronize savegame data +	 */ +	void synchronize(Common::Serializer &s); -	void load(Common::SeekableReadStream *stream); -public:  	/** -	 * Synchronizes a boolean array as a bitfield set +	 * Support method that generates a savegame name +	 * @param slot		Slot number  	 */ -	static void syncBitFlags(Common::Serializer &s, bool *startP, bool *endP); +	Common::String generateSaveName(int slot); + +	/** +	 * Initializes a new savegame +	 */ +	void reset();  public:  	bool _wonWorld;  	bool _wonDarkSide;  public: -	SavesManager(XeenEngine *vm, Party &party); - +	SavesManager(const Common::String &targetName);  	~SavesManager(); -	/** -	 * Sets up the dynamic data for the game for a new game -	 */ -	void reset(); -  	void readCharFile();  	void writeCharFile();  	void saveChars(); -	// Archive implementation -	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +	/** +	 * Read in a savegame header +	 */ +	static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header); + +	/** +	 * Write out a savegame header +	 */ +	void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header); + +	/** +	 * Load a savegame +	 */ +	Common::Error loadGameState(int slot); + +	/** +	 * Save the game +	 */ +	Common::Error saveGameState(int slot, const Common::String &desc);  };  } // End of namespace Xeen diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 255e5ceb55..53303c384b 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -36,7 +36,7 @@ Spells::Spells(XeenEngine *vm) : _vm(vm) {  }  void Spells::load() { -	File f1("spells.xen"); +	File f1("spells.xen", 1);  	while (f1.pos() < f1.size())  		_spellNames.push_back(f1.readString());  	f1.close(); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 39e5f4b7b5..9a0e42e44c 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -25,8 +25,6 @@  #include "common/debug-channels.h"  #include "common/events.h"  #include "engines/util.h" -#include "graphics/scaler.h" -#include "graphics/thumbnail.h"  #include "xeen/xeen.h"  #include "xeen/files.h"  #include "xeen/resources.h" @@ -99,14 +97,14 @@ void XeenEngine::initialize() {  	_locations = new LocationManager();  	_map = new Map(this);  	_party = new Party(this); -	_saves = new SavesManager(this, *_party); +	_saves = new SavesManager(_targetName);  	_screen = new Screen(this);  	_scripts = new Scripts(this);  	_sound = new Sound(this, _mixer);  	_spells = new Spells(this);  	_windows = new Windows(); -	File f("029.obj"); +	File f("029.obj", 1);  	_eventData = f.readStream(f.size());  	// Set graphics mode @@ -137,51 +135,11 @@ int XeenEngine::getRandomNumber(int minNumber, int maxNumber) {  }  Common::Error XeenEngine::saveGameState(int slot, const Common::String &desc) { -	Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( -		generateSaveName(slot)); -	if (!out) -		return Common::kCreatingFileFailed; - -	XeenSavegameHeader header; -	header._saveName = desc; -	writeSavegameHeader(out, header); - -	Common::Serializer s(nullptr, out); -	synchronize(s); - -	out->finalize(); -	delete out; - -	return Common::kNoError; +	return _saves->saveGameState(slot, desc);  }  Common::Error XeenEngine::loadGameState(int slot) { -	Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( -		generateSaveName(slot)); -	if (!saveFile) -		return Common::kReadingFailed; - -	Common::Serializer s(saveFile, nullptr); - -	// Load the savaegame header -	XeenSavegameHeader header; -	if (!readSavegameHeader(saveFile, header)) -		error("Invalid savegame"); - -	if (header._thumbnail) { -		header._thumbnail->free(); -		delete header._thumbnail; -	} - -	// Load most of the savegame data -	synchronize(s); -	delete saveFile; - -	return Common::kNoError; -} - -Common::String XeenEngine::generateSaveName(int slot) { -	return Common::String::format("%s.%03d", _targetName.c_str(), slot); +	return _saves->loadGameState(slot);  }  bool XeenEngine::canLoadGameStateCurrently() { @@ -192,81 +150,7 @@ bool XeenEngine::canSaveGameStateCurrently() {  	return true;  } -void XeenEngine::synchronize(Common::Serializer &s) { -	// TODO -} - -const char *const SAVEGAME_STR = "XEEN"; -#define SAVEGAME_STR_SIZE 6 - -bool XeenEngine::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header) { -	char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; -	header._thumbnail = nullptr; - -	// Validate the header Id -	in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); -	if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) -		return false; - -	header._version = in->readByte(); -	if (header._version > XEEN_SAVEGAME_VERSION) -		return false; - -	// Read in the string -	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._year = in->readSint16LE(); -	header._month = in->readSint16LE(); -	header._day = in->readSint16LE(); -	header._hour = in->readSint16LE(); -	header._minute = in->readSint16LE(); -	header._totalFrames = in->readUint32LE(); - -	return true; -} - -void XeenEngine::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header) { -	// Write out a savegame header -	out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); - -	out->writeByte(XEEN_SAVEGAME_VERSION); - -	// Write savegame name -	out->writeString(header._saveName); -	out->writeByte('\0'); - -	// Write a thumbnail of the screen -/* -	uint8 thumbPalette[768]; -	_screen->getPalette(thumbPalette); -	Graphics::Surface saveThumb; -	::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(), -		_screen->w, _screen->h, thumbPalette); -	Graphics::saveThumbnail(*out, saveThumb); -	saveThumb.free(); -*/ -	// Write out the save date/time -	TimeDate td; -	g_system->getTimeAndDate(td); -	out->writeSint16LE(td.tm_year + 1900); -	out->writeSint16LE(td.tm_mon + 1); -	out->writeSint16LE(td.tm_mday); -	out->writeSint16LE(td.tm_hour); -	out->writeSint16LE(td.tm_min); -//	out->writeUint32LE(_events->getFrameCounter()); -} -  void XeenEngine::playGame() { -	_saves->reset();  	_files->setGameCc(0);  	_sound->stopAllAudio(); diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index 022ad6673a..afbec4a7f9 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -27,7 +27,6 @@  #include "common/system.h"  #include "common/error.h"  #include "common/random.h" -#include "common/savefile.h"  #include "common/serializer.h"  #include "common/util.h"  #include "engines/engine.h" @@ -124,17 +123,6 @@ protected:  private:  	void initialize(); -	/** -	 * Synchronize savegame data -	 */ -	void synchronize(Common::Serializer &s); - -	/** -	 * Support method that generates a savegame name -	 * @param slot		Slot number -	 */ -	Common::String generateSaveName(int slot); -  	// Engine APIs  	virtual Common::Error run();  	virtual bool hasFeature(EngineFeature f) const; @@ -196,16 +184,6 @@ public:  	*/  	bool canSaveGameStateCurrently(); -	/** -	 * Read in a savegame header -	 */ -	static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header); - -	/** -	 * Write out a savegame header -	 */ -	void writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header); -  	static Common::String printMil(uint value);  	static Common::String printK(uint value);  | 
