[Scummvm-git-logs] scummvm master -> 531467581f6ce923fda54eb8bf24cae28739b5ce

dreammaster dreammaster at scummvm.org
Sat Jan 13 03:22:15 CET 2018


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
531467581f XEEN: Further savegame logic


Commit: 531467581f6ce923fda54eb8bf24cae28739b5ce
    https://github.com/scummvm/scummvm/commit/531467581f6ce923fda54eb8bf24cae28739b5ce
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-01-12T21:22:06-05:00

Commit Message:
XEEN: Further savegame logic

Changed paths:
    engines/xeen/dialogs_party.cpp
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/locations.cpp
    engines/xeen/saves.cpp
    engines/xeen/saves.h
    engines/xeen/scripts.cpp


diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index f4d95ca..64f57d6 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -133,7 +133,7 @@ void PartyDialog::execute() {
 					party._mazeId = party._priorMazeId;
 
 					party.copyPartyToRoster();
-					_vm->_saves->writeCharFile();
+					//_vm->_saves->writeCharFile();
 					return;
 				}
 				break;
@@ -208,7 +208,7 @@ void PartyDialog::execute() {
 					createChar();
 
 					party.copyPartyToRoster();
-					_vm->_saves->writeCharFile();
+					//_vm->_saves->writeCharFile();
 					screen.fadeOut();
 					modeFlag = true;
 					breakFlag = true;
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 0ed6dbd..912c953 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -56,18 +56,17 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
 	return total;
 }
 
-void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) {
-	int count = stream->readUint16LE();
+void BaseCCArchive::loadIndex(Common::SeekableReadStream &stream) {
+	int count = stream.readUint16LE();
 
 	// Read in the data for the archive's index
 	byte *rawIndex = new byte[count * 8];
-	stream->read(rawIndex, count * 8);
+	stream.read(rawIndex, count * 8);
 
 	// Decrypt the index
-	int ah = 0xac;
-	for (int i = 0; i < count * 8; ++i) {
-		rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff);
-		ah += 0x67;
+	int seed = 0xac;
+	for (int i = 0; i < count * 8; ++i, seed += 0x67) {
+		rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + seed) & 0xff);
 	}
 
 	// Extract the index data into entry structures
@@ -86,14 +85,51 @@ void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) {
 	delete[] rawIndex;
 }
 
+void BaseCCArchive::saveIndex(Common::WriteStream &stream) {
+	// First caclculate file offsets for each resource, since replaced resources
+	// will shift file offsets for even the succeeding unchanged resources
+	for (uint idx = 1, pos = _index[0]._offset + _index[0]._size; idx < _index.size(); ++idx) {
+		_index[idx]._offset = pos;
+		pos += _index[idx]._size;
+	}
+
+	// Fill up the data for the index entries into a raw data block
+	byte data[8];
+	byte *rawIndex = new byte[_index.size() * 8];
+
+	byte *entryP = rawIndex;
+	for (uint i = 0; i < _index.size(); ++i, entryP += 8) {
+		CCEntry &entry = _index[i];
+		WRITE_LE_UINT16(&entryP[0], entry._id);
+		WRITE_LE_UINT32(&entryP[2], entry._offset);
+		WRITE_LE_UINT16(&entryP[5], entry._size);
+		entryP[7] = 0;
+	}
+
+	// Encrypt the index
+	int seed = 0xac;
+	for (uint i = 0; i < _index.size() * 8; ++i, seed += 0x67) {
+		byte b = (seed - rawIndex[i]) && 0xff;
+		rawIndex[i] = ((b >> 2) & 0x3f) | ((b & 3) << 6);
+	}
+
+	// Write out the number of entries and the encrypted index data
+	stream.writeUint16LE(_index.size());
+	stream.write(rawIndex, _index.size() * 8);
+
+	delete[] rawIndex;
+}
+
 bool BaseCCArchive::hasFile(const Common::String &name) const {
 	CCEntry ccEntry;
 	return getHeaderEntry(name, ccEntry);
 }
 
 bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
-	uint16 id = convertNameToId(resourceName);
+	return getHeaderEntry(convertNameToId(resourceName), ccEntry);
+}
 
+bool BaseCCArchive::getHeaderEntry(uint16 id, CCEntry &ccEntry) const {
 	// Loop through the index
 	for (uint i = 0; i < _index.size(); ++i) {
 		if (_index[i]._id == id) {
@@ -123,7 +159,7 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
 CCArchive::CCArchive(const Common::String &filename, bool encoded):
 		BaseCCArchive(), _filename(filename), _encoded(encoded) {
 	File f(filename, SearchMan);
-	loadIndex(&f);
+	loadIndex(f);
 }
 
 CCArchive::CCArchive(const Common::String &filename, const Common::String &prefix,
@@ -131,7 +167,7 @@ CCArchive::CCArchive(const Common::String &filename, const Common::String &prefi
 		_prefix(prefix), _encoded(encoded) {
 	_prefix.toLowercase();
 	File f(filename, SearchMan);
-	loadIndex(&f);
+	loadIndex(f);
 }
 
 CCArchive::~CCArchive() {
@@ -371,18 +407,22 @@ SaveArchive::~SaveArchive() {
 }
 
 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);
+	return createReadStreamForMember(id);
+}
+
+Common::SeekableReadStream *SaveArchive::createReadStreamForMember(uint16 id) const {
 	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)) {
+	CCEntry ccEntry;
+	if (getHeaderEntry(id, ccEntry)) {
 		// Open the correct CC entry
 		return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size);
 	}
@@ -390,14 +430,14 @@ Common::SeekableReadStream *SaveArchive::createReadStreamForMember(const Common:
 	return nullptr;
 }
 
-void SaveArchive::load(Common::SeekableReadStream *stream) {
+void SaveArchive::load(Common::SeekableReadStream &stream) {
 	loadIndex(stream);
 
 	delete[] _data;
-	_dataSize = stream->size();
+	_dataSize = stream.size();
 	_data = new byte[_dataSize];
-	stream->seek(0);
-	stream->read(_data, _dataSize);
+	stream.seek(0);
+	stream.read(_data, _dataSize);
 
 	// Load in the character stats and active party
 	Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr");
@@ -434,12 +474,53 @@ void SaveArchive::reset(CCArchive *src) {
 
 	assert(saveFile.size() > 0);
 	Common::MemoryReadStream f(saveFile.getData(), saveFile.size());
-	load(&f);
+	load(f);
 }
 
 void SaveArchive::save(Common::WriteStream &s) {
-	s.writeUint32LE(_dataSize);
-	s.write(_data, _dataSize);
+	// Save the character stats and active party
+	OutFile chr("maze.chr", this);
+	XeenSerializer sChr(nullptr, &chr);
+	_party->_roster.synchronize(sChr);
+
+	OutFile pty("maze.pty", this);
+	Common::Serializer sPty(nullptr, &pty);
+	_party->synchronize(sPty);
+
+	// Save out the index
+	saveIndex(s);
+
+	// Save out each resource in turn
+	for (uint idx = 0; idx < _index.size(); ++idx) {
+		// Get the entry
+		Common::SeekableReadStream *entry = createReadStreamForMember(_index[idx]._id);
+		byte *data = new byte[entry->size()];
+		entry->read(data, entry->size());
+
+		// Write it out to the savegame
+		s.write(data, entry->size());
+		delete[] data;
+		delete entry;
+	}
+}
+
+void SaveArchive::replaceEntry(uint16 id, const byte *data, size_t size) {
+	// Delete any prior set entry
+	if (_newData.contains(id))
+		delete _newData[id];
+
+	// Create a new entry and write out the data to it
+	Common::MemoryWriteStreamDynamic *out = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+	out->write(data, size);
+	_newData[id] = out;
+
+	// Update the index with the entry's size for later convenience when creating savegames
+	for (uint idx = 0; idx < _index.size(); ++idx) {
+		if (_index[idx]._id == id) {
+			_index[idx]._size = size;
+			break;
+		}
+	}
 }
 
 /*------------------------------------------------------------------------*/
@@ -470,11 +551,7 @@ int32 OutFile::pos() const {
 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());
+	_archive->replaceEntry(id, _backingStream.getData(), _backingStream.size());
 }
 
 } // End of namespace Xeen
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index b5636b1..b528658 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -213,13 +213,24 @@ protected:
 	/**
 	 * Load the index of a given CC file
 	 */
-	void loadIndex(Common::SeekableReadStream *stream);
+	void loadIndex(Common::SeekableReadStream &stream);
+
+	/**
+	 * Saves out the contents of the index. Used when creating savegames
+	 */
+	void saveIndex(Common::WriteStream &stream);
 
 	/**
 	 * Given a resource name, returns whether an entry exists, and returns
 	 * the header index data for that entry
 	 */
 	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+
+	/**
+	 * Given a resource Id, returns whether an entry exists, and returns
+	 * the header index data for that entry
+	 */
+	virtual bool getHeaderEntry(uint16 id, CCEntry &ccEntry) const;
 public:
 	/**
 	 * Hash a given filename to produce the Id that represents it
@@ -275,14 +286,24 @@ public:
 	virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 
 	/**
+	 * Archive implementation
+	 */
+	virtual Common::SeekableReadStream *createReadStreamForMember(uint16 id) const;
+
+	/**
 	 * Loads a save archive from a stream
 	 */
-	void load(Common::SeekableReadStream *stream);
+	void load(Common::SeekableReadStream &stream);
 
 	/**
 	 * Saves a save archive to a savegame
 	 */
 	void save(Common::WriteStream &s);
+
+	/**
+	 * Sets a new resource entry
+	 */
+	void replaceEntry(uint16 id, const byte *data, size_t size);
 };
 
 /**
diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp
index 1139173..647eeba 100644
--- a/engines/xeen/locations.cpp
+++ b/engines/xeen/locations.cpp
@@ -104,7 +104,7 @@ int BaseLocation::show() {
 		party.addTime(_farewellTime);
 		result = 0;
 	} else {
-		_vm->_saves->saveChars();
+		//_vm->_saves->saveChars();
 		result = 2;
 	}
 
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 0bc4129..2a6b7d6 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -62,18 +62,6 @@ SavesManager::~SavesManager() {
 	delete File::_darkSave;
 }
 
-void SavesManager::readCharFile() {
-	warning("TODO: readCharFile");
-}
-
-void SavesManager::writeCharFile() {
-	warning("TODO: writeCharFile");
-}
-
-void SavesManager::saveChars() {
-	warning("TODO: saveChars");
-}
-
 const char *const SAVEGAME_STR = "XEEN";
 #define SAVEGAME_STR_SIZE 6
 
@@ -151,6 +139,11 @@ Common::Error SavesManager::saveGameState(int slot, const Common::String &desc)
 	if (!out)
 		return Common::kCreatingFileFailed;
 
+	// Push map and party data to the save archives
+	Map &map = *g_vm->_map;
+	map.saveMaze();
+
+
 	XeenSavegameHeader header;
 	header._saveName = desc;
 	writeSavegameHeader(out, header);
@@ -199,7 +192,7 @@ Common::Error SavesManager::loadGameState(int slot) {
 		if (archives[idx]) {
 			Common::SeekableSubReadStream arcStream(saveFile, saveFile->pos(),
 				saveFile->pos() + fileSize);
-			archives[idx]->load(&arcStream);
+			archives[idx]->load(arcStream);
 		} else {
 			assert(!fileSize);
 		}
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index 334ea3d..c236bee 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -62,12 +62,6 @@ public:
 	SavesManager(const Common::String &targetName);
 	~SavesManager();
 
-	void readCharFile();
-
-	void writeCharFile();
-
-	void saveChars();
-
 	/**
 	 * Read in a savegame header
 	 */
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 9960322..46485a5 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -1425,7 +1425,7 @@ void Scripts::doWorldEnding() {
 }
 
 void Scripts::doEnding(const Common::String &endStr) {
-	_vm->_saves->saveChars();
+	//_vm->_saves->saveChars();
 
 	Party &party = *_vm->_party;
 





More information about the Scummvm-git-logs mailing list