[Scummvm-git-logs] scummvm master -> 700bcc73e1b829cb15b1dcc56027b8da364c2468

dreammaster dreammaster at scummvm.org
Sun Jan 14 20:17:08 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:
700bcc73e1 XEEN: Fixes for encryption and resource offsets in save files


Commit: 700bcc73e1b829cb15b1dcc56027b8da364c2468
    https://github.com/scummvm/scummvm/commit/700bcc73e1b829cb15b1dcc56027b8da364c2468
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2018-01-14T14:16:58-05:00

Commit Message:
XEEN: Fixes for encryption and resource offsets in save files

Changed paths:
    engines/xeen/files.cpp
    engines/xeen/files.h
    engines/xeen/saves.cpp


diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 164313c..0c6ff1d 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -88,12 +88,13 @@ void BaseCCArchive::loadIndex(Common::SeekableReadStream &stream) {
 void BaseCCArchive::saveIndex(Common::WriteStream &stream) {
 	// Fill up the data for the index entries into a raw data block
 	byte *rawIndex = new byte[_index.size() * 8];
+	byte b;
 
 	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_UINT32(&entryP[2], entry._writeOffset);
 		WRITE_LE_UINT16(&entryP[5], entry._size);
 		entryP[7] = 0;
 	}
@@ -101,8 +102,11 @@ void BaseCCArchive::saveIndex(Common::WriteStream &stream) {
 	// Encrypt the index
 	int seed = 0xac;
 	for (uint i = 0; i < _index.size() * 8; ++i, seed += 0x67) {
-		byte b = (rawIndex[i] - seed) & 0xff;
-		rawIndex[i] = (byte)((b >> 2) | (b << 6));
+		b = (rawIndex[i] - seed) & 0xff;
+		b = (byte)((b >> 2) | (b << 6));
+
+		assert(rawIndex[i] == (byte)((((b << 2) | (b >> 6)) + seed) & 0xff));
+		rawIndex[i] = b;
 	}
 
 	// Write out the number of entries and the encrypted index data
@@ -489,19 +493,19 @@ void SaveArchive::save(Common::WriteStream &s) {
 	_party->synchronize(sPty);
 	pty.finalize();
 
-	// 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;
+	// First caclculate new offsets and total filesize
+	_dataSize = _index.size() * 8 + 2;
+	for (uint idx = 0; idx < _index.size(); ++idx) {
+		_index[idx]._writeOffset = (idx == 0) ? _dataSize :
+			_index[idx - 1]._writeOffset + _index[idx - 1]._size;
+		_dataSize += _index[idx]._size;
 	}
 
-	// Write out the size of the save archive
-	_dataSize = _index.back()._offset + _index.back()._size;
 	s.writeUint32LE(_dataSize);
 
 	// Save out the index
-	saveIndex(s);
+	SubWriteStream dataStream(&s);
+	saveIndex(dataStream);
 
 	// Save out each resource in turn
 	for (uint idx = 0; idx < _index.size(); ++idx) {
@@ -511,7 +515,8 @@ void SaveArchive::save(Common::WriteStream &s) {
 		entry->read(data, entry->size());
 
 		// Write it out to the savegame
-		s.write(data, entry->size());
+		assert(dataStream.pos() == _index[idx]._writeOffset);
+		dataStream.write(data, entry->size());
 		delete[] data;
 		delete entry;
 	}
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index ff10db5..37b2422 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -64,8 +64,9 @@ struct CCEntry {
 	uint16 _id;
 	uint32 _offset;
 	uint16 _size;
+	uint32 _writeOffset;
 
-	CCEntry() : _id(0), _offset(0), _size(0) {}
+	CCEntry() : _id(0), _offset(0), _size(0), _writeOffset(0) {}
 	CCEntry(uint16 id, uint32 offset, uint32 size)
 		: _id(id), _offset(offset), _size(size) {
 	}
@@ -185,6 +186,30 @@ public:
 	static bool exists(const Common::String &filename, int ccMode);
 };
 
+/**
+ * SubWriteStream provides a way of compartmentalizing writing to a subsection of
+ * a file. This is primarily useful for the pos() function which can, for example,
+ * be used in asserts to ensure writing is being done at the correct offset within
+ * the bounds of the structure being written.
+*/
+class SubWriteStream : virtual public Common::WriteStream {
+protected:
+	Common::WriteStream *_parentStream;
+	uint32 _begin;
+	DisposeAfterUse::Flag _disposeAfterUse;
+public:
+	SubWriteStream(Common::WriteStream *parentStream) :
+		_parentStream(parentStream),  _begin(parentStream->pos()) {
+	}
+
+	virtual uint32 write(const void *dataPtr, uint32 dataSize) {
+		return _parentStream->write(dataPtr, dataSize);
+	}
+	virtual bool flush() { return _parentStream->flush(); }
+	virtual void finalize() {}
+	virtual int32 pos() const { return _parentStream->pos() - _begin; }
+};
+
 class StringArray : public Common::StringArray {
 public:
 	StringArray() {}
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index f84176c..166cf6f 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -143,7 +143,7 @@ Common::Error SavesManager::saveGameState(int slot, const Common::String &desc)
 	Map &map = *g_vm->_map;
 	map.saveMaze();
 
-
+	// Write the savegame header
 	XeenSavegameHeader header;
 	header._saveName = desc;
 	writeSavegameHeader(out, header);





More information about the Scummvm-git-logs mailing list