1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/util.h"
24 #include "common/endian.h"
25 #include "common/memstream.h"
26 #include "common/system.h"
27 #include "common/savefile.h"
28 
29 #include "gob/gob.h"
30 #include "gob/save/savefile.h"
31 #include "gob/video.h"
32 #include "gob/inter.h"
33 #include "gob/variables.h"
34 
35 namespace Gob {
36 
flushStream(Common::WriteStream & stream)37 static inline bool flushStream(Common::WriteStream &stream) {
38 	// Flush and check for errors
39 
40 	if (!stream.flush())
41 		return false;
42 	if (stream.err())
43 		return false;
44 
45 	return true;
46 }
47 
SaveHeader(uint32 type,uint32 version,uint32 size)48 SaveHeader::SaveHeader(uint32 type, uint32 version, uint32 size) {
49 	_type = type;
50 	_version = version;
51 	_size = size;
52 }
53 
read(Common::ReadStream & stream)54 bool SaveHeader::read(Common::ReadStream &stream) {
55 	// Read the header and verify the global IDs
56 	if (stream.readUint32BE() != kID1)
57 		return false;
58 	if (stream.readUint32BE() != kID2)
59 		return false;
60 
61 	_type = stream.readUint32BE();
62 	_version = stream.readUint32LE();
63 	_size = stream.readUint32LE();
64 
65 	return !stream.err();
66 }
67 
verify(Common::ReadStream & stream) const68 bool SaveHeader::verify(Common::ReadStream &stream) const {
69 	// Compare the header with the stream's content
70 
71 	if (stream.readUint32BE() != kID1)
72 		return false;
73 	if (stream.readUint32BE() != kID2)
74 		return false;
75 	if (stream.readUint32BE() != _type)
76 		return false;
77 	if (stream.readUint32LE() != _version)
78 		return false;
79 	if (stream.readUint32LE() != _size)
80 		return false;
81 
82 	return !stream.err();
83 }
84 
operator ==(const SaveHeader & header) const85 bool SaveHeader::operator==(const SaveHeader &header) const {
86 	return (_type    == header._type)    &&
87 	       (_version == header._version) &&
88 	       (_size    == header._size);
89 }
90 
operator !=(const SaveHeader & header) const91 bool SaveHeader::operator!=(const SaveHeader &header) const {
92 	return !(*this == header);
93 }
94 
verifyReadSize(Common::ReadStream & stream)95 bool SaveHeader::verifyReadSize(Common::ReadStream &stream) {
96 	// Compare the header with the stream's content, expect for the size
97 
98 	if (stream.readUint32BE() != kID1)
99 		return false;
100 	if (stream.readUint32BE() != kID2)
101 		return false;
102 	if (stream.readUint32BE() != _type)
103 		return false;
104 	if (stream.readUint32LE() != _version)
105 		return false;
106 
107 	// Read the size out of the stream instead
108 	_size = stream.readUint32LE();
109 
110 	return !stream.err();
111 }
112 
write(Common::WriteStream & stream) const113 bool SaveHeader::write(Common::WriteStream &stream) const {
114 	stream.writeUint32BE(kID1);
115 	stream.writeUint32BE(kID2);
116 	stream.writeUint32BE(_type);
117 	stream.writeUint32LE(_version);
118 	stream.writeUint32LE(_size);
119 
120 	return flushStream(stream);
121 }
122 
getType() const123 uint32 SaveHeader::getType() const {
124 	return _type;
125 }
126 
getVersion() const127 uint32 SaveHeader::getVersion() const {
128 	return _version;
129 }
130 
getSize() const131 uint32 SaveHeader::getSize() const {
132 	return _size;
133 }
134 
setType(uint32 type)135 void SaveHeader::setType(uint32 type) {
136 	_type = type;
137 }
138 
setVersion(uint32 version)139 void SaveHeader::setVersion(uint32 version) {
140 	_version = version;
141 }
142 
setSize(uint32 size)143 void SaveHeader::setSize(uint32 size) {
144 	_size = size;
145 }
146 
SavePart()147 SavePart::SavePart() {
148 }
149 
~SavePart()150 SavePart::~SavePart() {
151 }
152 
getSize() const153 uint32 SavePart::getSize() const {
154 	// A part's size is the content's size plus the header's size
155 	return _header.getSize() + SaveHeader::kSize;
156 }
157 
SavePartMem(uint32 size)158 SavePartMem::SavePartMem(uint32 size) : SavePart(), _size(size) {
159 	_header.setType(kID);
160 	_header.setVersion(kVersion);
161 	_header.setSize(size);
162 
163 	_data = new byte[size];
164 }
165 
~SavePartMem()166 SavePartMem::~SavePartMem() {
167 	delete[] _data;
168 }
169 
read(Common::ReadStream & stream)170 bool SavePartMem::read(Common::ReadStream &stream) {
171 	if (!_header.verify(stream))
172 		return false;
173 
174 	if (stream.read(_data, _size) != _size)
175 		return false;
176 
177 	return !stream.err();
178 }
179 
write(Common::WriteStream & stream) const180 bool SavePartMem::write(Common::WriteStream &stream) const {
181 	if (!_header.write(stream))
182 		return false;
183 
184 	if (stream.write(_data, _size) != _size)
185 		return false;
186 
187 	return flushStream(stream);
188 }
189 
readFrom(const byte * data,uint32 offset,uint32 size)190 bool SavePartMem::readFrom(const byte *data, uint32 offset, uint32 size) {
191 	if ((offset + size) > _size)
192 		return false;
193 
194 	memcpy(_data + offset, data, size);
195 
196 	return true;
197 }
198 
writeInto(byte * data,uint32 offset,uint32 size) const199 bool SavePartMem::writeInto(byte *data, uint32 offset, uint32 size) const {
200 	if ((offset + size) > _size)
201 		return false;
202 
203 	memcpy(data, _data + offset, size);
204 
205 	return true;
206 }
207 
SavePartVars(GobEngine * vm,uint32 size)208 SavePartVars::SavePartVars(GobEngine *vm, uint32 size) : SavePart(), _size(size), _vm(vm) {
209 	_header.setType(kID);
210 	_header.setVersion(kVersion);
211 	_header.setSize(size);
212 
213 	_data = new byte[size];
214 }
215 
~SavePartVars()216 SavePartVars::~SavePartVars() {
217 	delete[] _data;
218 }
219 
read(Common::ReadStream & stream)220 bool SavePartVars::read(Common::ReadStream &stream) {
221 	if (!_header.verify(stream))
222 		return false;
223 
224 	if (stream.read(_data, _size) != _size)
225 		return false;
226 
227 	return !stream.err();
228 }
229 
write(Common::WriteStream & stream) const230 bool SavePartVars::write(Common::WriteStream &stream) const {
231 	if (!_header.write(stream))
232 		return false;
233 
234 	if (stream.write(_data, _size) != _size)
235 		return false;
236 
237 	return flushStream(stream);
238 }
239 
readFrom(uint32 var,uint32 offset,uint32 size)240 bool SavePartVars::readFrom(uint32 var, uint32 offset, uint32 size) {
241 	if (!_vm->_inter->_variables)
242 		return false;
243 
244 	if ((offset + size) > _size)
245 		return false;
246 
247 	// Get raw variables
248 	return _vm->_inter->_variables->copyTo(var, _data + offset, size);
249 }
250 
readFromRaw(const byte * data,uint32 size)251 bool SavePartVars::readFromRaw(const byte *data, uint32 size) {
252 	if (size != _size)
253 		return false;
254 
255 	memcpy(_data, data, size);
256 	return true;
257 }
258 
writeInto(uint32 var,uint32 offset,uint32 size) const259 bool SavePartVars::writeInto(uint32 var, uint32 offset, uint32 size) const {
260 	if (!_vm->_inter->_variables)
261 		return false;
262 
263 	if ((offset + size) > _size)
264 		return false;
265 
266 	// Write raw variables
267 	if (!_vm->_inter->_variables->copyFrom(var, _data + offset, size))
268 		return false;
269 
270 	return true;
271 }
272 
SavePartSprite(uint32 width,uint32 height,bool trueColor)273 SavePartSprite::SavePartSprite(uint32 width, uint32 height, bool trueColor) {
274 	assert((width > 0) && (height > 0));
275 
276 	_width = width;
277 	_height = height;
278 
279 	_oldFormat = false;
280 	_trueColor = trueColor;
281 
282 	_header.setType(kID);
283 	_header.setVersion(kVersion);
284 
285 	_spriteSize = _width * _height;
286 	if (_trueColor)
287 		_spriteSize *= 3;
288 
289 		//          width + height + color +    sprite   + palette
290 	_header.setSize(4   +   4    +   1   + _spriteSize + 768);
291 
292 	_dataSprite  = new byte[_spriteSize];
293 	_dataPalette = new byte[768];
294 
295 	memset(_dataSprite,  0, _spriteSize);
296 	memset(_dataPalette, 0, 768);
297 }
298 
~SavePartSprite()299 SavePartSprite::~SavePartSprite() {
300 	delete[] _dataSprite;
301 	delete[] _dataPalette;
302 }
303 
read(Common::ReadStream & stream)304 bool SavePartSprite::read(Common::ReadStream &stream) {
305 	SaveHeader header;
306 	header.read(stream);
307 
308 	if (_header != header) {
309 		if (!_trueColor) {
310 			// Header validation failed, trying again with the old version
311 
312 			_header.setVersion(1);
313 			_header.setSize(_header.getSize() - 1);
314 
315 			if (_header != header)
316 				// Nope, isn't it either
317 				return false;
318 
319 			_oldFormat = true;
320 
321 			_header.setVersion(kVersion);
322 			_header.setSize(_header.getSize() + 1);
323 
324 		} else
325 			return false;
326 	}
327 
328 	// The sprite's dimensions have to fit
329 	if (stream.readUint32LE() != _width)
330 		return false;
331 	if (stream.readUint32LE() != _height)
332 		return false;
333 
334 	// If it's in the current format, the true color flag has to be the same too
335 	if (!_oldFormat)
336 		if ((stream.readByte() != 0) != _trueColor)
337 			return false;
338 
339 	// Sprite data
340 	if (stream.read(_dataSprite, _spriteSize) != _spriteSize)
341 		return false;
342 
343 	// Palette data
344 	if (stream.read(_dataPalette, 768) != 768)
345 		return false;
346 
347 	return !stream.err();
348 }
349 
write(Common::WriteStream & stream) const350 bool SavePartSprite::write(Common::WriteStream &stream) const {
351 	if (!_header.write(stream))
352 		return false;
353 
354 	// The sprite's dimensions
355 	stream.writeUint32LE(_width);
356 	stream.writeUint32LE(_height);
357 	stream.writeByte(_trueColor);
358 
359 	// Sprite data
360 	if (stream.write(_dataSprite, _spriteSize) != _spriteSize)
361 		return false;
362 
363 	// Palette data
364 	if (stream.write(_dataPalette, 768) != 768)
365 		return false;
366 
367 	return flushStream(stream);
368 }
369 
readPalette(const byte * palette)370 bool SavePartSprite::readPalette(const byte *palette) {
371 	memcpy(_dataPalette, palette, 768);
372 
373 	return true;
374 }
375 
readSprite(const Surface & sprite)376 bool SavePartSprite::readSprite(const Surface &sprite) {
377 	// The sprite's dimensions have to fit
378 	if (((uint32)sprite.getWidth()) != _width)
379 		return false;
380 	if (((uint32)sprite.getHeight()) != _height)
381 		return false;
382 
383 	if (_trueColor) {
384 		if (sprite.getBPP() <= 1)
385 			return false;
386 
387 		Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
388 
389 		byte *data = _dataSprite;
390 		ConstPixel pixel = sprite.get();
391 		for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3)
392 			pixelFormat.colorToRGB(pixel.get(), data[0], data[1], data[2]);
393 
394 	} else {
395 		if (sprite.getBPP() != 1)
396 			return false;
397 
398 		memcpy(_dataSprite, sprite.getData(), _width * _height);
399 	}
400 
401 	return true;
402 }
403 
readSpriteRaw(const byte * data,uint32 size)404 bool SavePartSprite::readSpriteRaw(const byte *data, uint32 size) {
405 	if (size != _spriteSize)
406 		return false;
407 
408 	memcpy(_dataSprite, data, size);
409 	return true;
410 }
411 
writePalette(byte * palette) const412 bool SavePartSprite::writePalette(byte *palette) const {
413 	memcpy(palette, _dataPalette, 768);
414 
415 	return true;
416 }
417 
writeSprite(Surface & sprite) const418 bool SavePartSprite::writeSprite(Surface &sprite) const {
419 	// The sprite's dimensions have to fit
420 	if (((uint32)sprite.getWidth()) != _width)
421 		return false;
422 	if (((uint32)sprite.getHeight()) != _height)
423 		return false;
424 
425 	if (_trueColor) {
426 		if (sprite.getBPP() <= 1)
427 			return false;
428 
429 		Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
430 
431 		const byte *data = _dataSprite;
432 		Pixel pixel = sprite.get();
433 		for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3)
434 			pixel.set(pixelFormat.RGBToColor(data[0], data[1], data[2]));
435 
436 	} else {
437 		if (sprite.getBPP() != 1)
438 			return false;
439 
440 		memcpy(sprite.getData(), _dataSprite, _spriteSize);
441 	}
442 
443 	return true;
444 }
445 
SavePartInfo(uint32 descMaxLength,uint32 gameID,uint32 gameVersion,byte endian,uint32 varCount)446 SavePartInfo::SavePartInfo(uint32 descMaxLength, uint32 gameID,
447 		uint32 gameVersion, byte endian, uint32 varCount) {
448 
449 	_header.setType(kID);
450 	_header.setVersion(kVersion);
451 	//                        descMaxLength + gameID + gameVersion + endian + varCount
452 	_header.setSize(descMaxLength + 4       +   4    +     4       +    1   +    4);
453 
454 	_descMaxLength = descMaxLength;
455 	_gameID = gameID;
456 	_gameVersion = gameVersion;
457 	_endian = endian;
458 	_varCount = varCount;
459 
460 	_desc = new char[_descMaxLength + 1];
461 	memset(_desc, 0, _descMaxLength + 1);
462 }
463 
~SavePartInfo()464 SavePartInfo::~SavePartInfo() {
465 	delete[] _desc;
466 }
467 
getDesc() const468 const char *SavePartInfo::getDesc() const {
469 	return _desc;
470 }
471 
getDescMaxLength() const472 uint32 SavePartInfo::getDescMaxLength() const {
473 	return _descMaxLength;
474 }
475 
setVarCount(uint32 varCount)476 void SavePartInfo::setVarCount(uint32 varCount) {
477 	_varCount = varCount;
478 }
479 
setDesc(const char * desc)480 void SavePartInfo::setDesc(const char *desc) {
481 	if (!desc) {
482 		memset(_desc, 0, _descMaxLength + 1);
483 		return;
484 	}
485 
486 	uint32 n = MIN<uint32>(strlen(desc), _descMaxLength);
487 
488 	// Copy the description and fill with 0
489 	memcpy(_desc, desc, n);
490 	memset(_desc + n, 0, _descMaxLength + 1 - n);
491 }
492 
setDesc(const byte * desc,uint32 size)493 void SavePartInfo::setDesc(const byte *desc, uint32 size) {
494 	if (!desc || !size) {
495 		memset(_desc, 0, _descMaxLength + 1);
496 		return;
497 	}
498 
499 	uint32 n = MIN<uint32>(size, _descMaxLength);
500 	memcpy(_desc, desc, n);
501 	memset(_desc + n, 0, _descMaxLength + 1 - n);
502 }
503 
read(Common::ReadStream & stream)504 bool SavePartInfo::read(Common::ReadStream &stream) {
505 	if (!_header.verify(stream))
506 		return false;
507 
508 	if (stream.readUint32LE() != _gameID)
509 		return false;
510 	if (stream.readUint32LE() != _gameVersion)
511 		return false;
512 	if (stream.readByte() != _endian)
513 		return false;
514 	if (stream.readUint32LE() != _varCount)
515 		return false;
516 	if (stream.readUint32LE() != _descMaxLength)
517 		return false;
518 
519 	if (stream.read(_desc, _descMaxLength) != _descMaxLength)
520 		return false;
521 
522 	_desc[_descMaxLength] = 0;
523 
524 	return !stream.err();
525 }
526 
write(Common::WriteStream & stream) const527 bool SavePartInfo::write(Common::WriteStream &stream) const {
528 	if (!_header.write(stream))
529 		return false;
530 
531 	stream.writeUint32LE(_gameID);
532 	stream.writeUint32LE(_gameVersion);
533 	stream.writeByte(_endian);
534 	stream.writeUint32LE(_varCount);
535 	stream.writeUint32LE(_descMaxLength);
536 
537 	if (stream.write(_desc, _descMaxLength) != _descMaxLength)
538 		return false;
539 
540 	return flushStream(stream);
541 }
542 
Part(uint32 s)543 SaveContainer::Part::Part(uint32 s) {
544 	size = s;
545 	data = new byte[size];
546 }
547 
~Part()548 SaveContainer::Part::~Part() {
549 	delete[] data;
550 }
551 
createWriteStream()552 Common::WriteStream *SaveContainer::Part::createWriteStream() {
553 	return new Common::MemoryWriteStream(data, size);
554 }
555 
createReadStream() const556 Common::ReadStream *SaveContainer::Part::createReadStream() const {
557 	return new Common::MemoryReadStream(data, size);
558 }
559 
SaveContainer(uint32 partCount,uint32 slot)560 SaveContainer::SaveContainer(uint32 partCount, uint32 slot) {
561 	assert(partCount > 0);
562 
563 	_slot = slot;
564 	_partCount = partCount;
565 
566 	_parts.resize(partCount);
567 	for (PartIterator it = _parts.begin(); it != _parts.end(); ++it)
568 		*it = 0;
569 
570 	_header.setType(kID);
571 	_header.setVersion(kVersion);
572 	_header.setSize(4); // uint32 # of parts
573 }
574 
~SaveContainer()575 SaveContainer::~SaveContainer() {
576 	clear();
577 }
578 
getSlot() const579 uint32 SaveContainer::getSlot() const {
580 	return _slot;
581 }
582 
getSize() const583 uint32 SaveContainer::getSize() const {
584 	return _header.getSize() + SaveHeader::kSize;
585 }
586 
hasAllParts() const587 bool SaveContainer::hasAllParts() const {
588 	for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it)
589 		if (!*it)
590 			return false;
591 
592 	return true;
593 }
594 
calcSize() const595 uint32 SaveContainer::calcSize() const {
596 	uint32 size = 4; // uint32 # of parts
597 
598 	for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it)
599 		if (*it)
600 			//              uint32 part size
601 			size += (*it)->size + 4;
602 
603 	return size;
604 }
605 
clear()606 void SaveContainer::clear() {
607 	for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
608 		Part *&p = *it;
609 
610 		delete p;
611 		p = 0;
612 	}
613 }
614 
writePart(uint32 partN,const SavePart * part)615 bool SaveContainer::writePart(uint32 partN, const SavePart *part) {
616 	// Sanity checks
617 	if (!part)
618 		return false;
619 	if (partN >= _partCount)
620 		return false;
621 
622 	Part *&p = _parts[partN];
623 
624 	delete p;
625 	// Create the part
626 	p = new Part(part->getSize());
627 
628 	Common::WriteStream *pStream = p->createWriteStream();
629 
630 	// Write
631 	if (!part->write(*pStream)) {
632 		delete p;
633 		p = 0;
634 
635 		delete pStream;
636 		return false;
637 	}
638 
639 	delete pStream;
640 
641 	// Update size
642 	_header.setSize(calcSize());
643 
644 	return true;
645 }
646 
readPart(uint32 partN,SavePart * part) const647 bool SaveContainer::readPart(uint32 partN, SavePart *part) const {
648 	// Sanity checks
649 	if (!part)
650 		return false;
651 	if (partN >= _partCount)
652 		return false;
653 
654 	const Part * const &p = _parts[partN];
655 
656 	// Check if the part actually exists
657 	if (!p)
658 		return false;
659 
660 	Common::ReadStream *pStream = p->createReadStream();
661 
662 	// Read
663 	if (!part->read(*pStream)) {
664 		delete pStream;
665 		return false;
666 	}
667 
668 	delete pStream;
669 	return true;
670 }
671 
readPartHeader(uint32 partN,SaveHeader * header) const672 bool SaveContainer::readPartHeader(uint32 partN, SaveHeader *header) const {
673 	// Sanity checks
674 	if (!header)
675 		return false;
676 	if (partN >= _partCount)
677 		return false;
678 
679 	const Part * const &p = _parts[partN];
680 
681 	// Check if the part actually exists
682 	if (!p)
683 		return false;
684 
685 	Common::ReadStream *pStream = p->createReadStream();
686 
687 	// Read
688 	if (!header->read(*pStream)) {
689 		delete pStream;
690 		return false;
691 	}
692 
693 	delete pStream;
694 	return true;
695 }
696 
read(Common::ReadStream & stream)697 bool SaveContainer::read(Common::ReadStream &stream) {
698 	// Verify the header and get the container's size
699 	if (!_header.verifyReadSize(stream))
700 		return false;
701 
702 	// The part count has to be correct
703 	if (stream.readUint32LE() != _partCount)
704 		return false;
705 
706 	// Iterate over all parts
707 	for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
708 		// Read the size
709 		uint32 size = stream.readUint32LE();
710 
711 		if (stream.err()) {
712 			clear();
713 			return false;
714 		}
715 
716 		Part *&p = *it;
717 
718 		delete p;
719 		// Create a suitable part
720 		p = new Part(size);
721 	}
722 
723 	// Update size
724 	_header.setSize(calcSize());
725 
726 	// Iterate over all parts
727 	for (PartIterator it = _parts.begin(); it != _parts.end(); ++it) {
728 		Part *&p = *it;
729 
730 		// Read the part
731 		if (stream.read(p->data, p->size) != p->size) {
732 			clear();
733 			return false;
734 		}
735 	}
736 
737 	return !stream.err();
738 }
739 
write(Common::WriteStream & stream) const740 bool SaveContainer::write(Common::WriteStream &stream) const {
741 	// Write the header
742 	if (!_header.write(stream))
743 		return false;
744 
745 	// Write the part count
746 	stream.writeUint32LE(_partCount);
747 
748 	// Iterate over all parts
749 	for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) {
750 		// Part doesn't actually exist => error
751 		if (!*it)
752 			return false;
753 
754 		// Write the part's size
755 		stream.writeUint32LE((*it)->size);
756 	}
757 
758 	if (!flushStream(stream))
759 		return false;
760 
761 	// Iterate over all parts
762 	for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) {
763 		Part * const &p = *it;
764 
765 		// Write the part
766 		if (stream.write(p->data, p->size) != p->size)
767 			return false;
768 	}
769 
770 	return flushStream(stream);
771 }
772 
getPartsInfo(Common::SeekableReadStream & stream)773 Common::Array<SaveContainer::PartInfo> *SaveContainer::getPartsInfo(Common::SeekableReadStream &stream) {
774 	Common::Array<PartInfo> *parts = 0;
775 
776 	// Remember the stream's position to seek back to
777 	uint32 startPos = stream.pos();
778 
779 	SaveHeader header;
780 
781 	header.setType(kID);
782 	header.setVersion(kVersion);
783 
784 	// Verify the header
785 	if (!header.verifyReadSize(stream)) {
786 		// Seek back
787 		stream.seek(startPos);
788 		return 0;
789 	}
790 
791 	// Read the part count
792 	uint32 partCount = stream.readUint32LE();
793 
794 	// Create a part information array
795 	parts = new Common::Array<PartInfo>;
796 	parts->resize(partCount);
797 
798 	// Read all part sizes
799 	for (uint32 i = 0; i < partCount; i++)
800 		(*parts)[i].size = stream.readUint32LE();
801 
802 	// Iterate over all parts
803 	for (uint32 i = 0; i < partCount; i++) {
804 		// The part's offset (from the starting point of the stream)
805 		(*parts)[i].offset = stream.pos() - startPos;
806 
807 		SaveHeader partHeader;
808 
809 		// Read the header
810 		if (!partHeader.read(stream)) {
811 			// Seek back
812 			stream.seek(startPos);
813 			delete parts;
814 			return 0;
815 		}
816 
817 		// Fill in the ID
818 		(*parts)[i].id = partHeader.getType();
819 
820 		// Skip the part's content
821 		stream.skip(partHeader.getSize());
822 	}
823 
824 	if (stream.err()) {
825 		delete parts;
826 		parts = 0;
827 	}
828 
829 	// Seek back
830 	stream.seek(startPos);
831 
832 	return parts;
833 }
834 
isSave(Common::SeekableReadStream & stream)835 bool SaveContainer::isSave(Common::SeekableReadStream &stream) {
836 	// Remember the stream's position to seek back to
837 	uint32 startPos = stream.pos();
838 
839 	SaveHeader header;
840 
841 	header.setType(kID);
842 	header.setVersion(kVersion);
843 
844 	bool result = header.verifyReadSize(stream);
845 
846 	// Seek back
847 	stream.seek(startPos);
848 
849 	return result;
850 }
851 
852 
SaveReader(uint32 partCount,uint32 slot,const Common::String & fileName)853 SaveReader::SaveReader(uint32 partCount, uint32 slot, const Common::String &fileName) :
854 	SaveContainer(partCount, slot), _fileName(fileName) {
855 
856 	_stream = 0;
857 
858 	_loaded = false;
859 }
860 
SaveReader(uint32 partCount,uint32 slot,Common::SeekableReadStream & stream)861 SaveReader::SaveReader(uint32 partCount, uint32 slot, Common::SeekableReadStream &stream) :
862 	SaveContainer(partCount, slot) {
863 
864 	_stream = &stream;
865 
866 	_loaded = false;
867 }
868 
~SaveReader()869 SaveReader::~SaveReader() {
870 }
871 
872 // Open the save and read it
load()873 bool SaveReader::load() {
874 
875 	Common::InSaveFile *in = 0;
876 	Common::SeekableReadStream *stream;
877 
878 	if (!_fileName.empty()) {
879 		in = openSave();
880 
881 		if (!in)
882 			return false;
883 
884 		stream = in;
885 	} else if (_stream)
886 		stream = _stream;
887 	else
888 		return false;
889 
890 	if (!SaveContainer::read(*stream)) {
891 		delete in;
892 		return false;
893 	}
894 
895 	delete in;
896 	_loaded = true;
897 	return true;
898 }
899 
readPartHeader(uint32 partN,SaveHeader * header) const900 bool SaveReader::readPartHeader(uint32 partN, SaveHeader *header) const {
901 	// The save has to be loaded
902 	if (!_loaded)
903 		return false;
904 
905 	return SaveContainer::readPartHeader(partN, header);
906 }
907 
readPart(uint32 partN,SavePart * part) const908 bool SaveReader::readPart(uint32 partN, SavePart *part) const {
909 	// The save has to be loaded
910 	if (!_loaded)
911 		return false;
912 
913 	if (!SaveContainer::readPart(partN, part))
914 		return false;
915 
916 	return true;
917 }
918 
openSave(const Common::String & fileName)919 Common::InSaveFile *SaveReader::openSave(const Common::String &fileName) {
920 	if (fileName.empty())
921 		return 0;
922 
923 	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
924 	return saveMan->openForLoading(fileName);
925 }
926 
openSave()927 Common::InSaveFile *SaveReader::openSave() {
928 	return openSave(_fileName);
929 }
930 
getInfo(Common::SeekableReadStream & stream,SavePartInfo & info)931 bool SaveReader::getInfo(Common::SeekableReadStream &stream, SavePartInfo &info) {
932 	// Remeber the stream's starting position to seek back to
933 	uint32 startPos = stream.pos();
934 
935 	// Get parts' basic information
936 	Common::Array<SaveContainer::PartInfo> *partsInfo = getPartsInfo(stream);
937 
938 	// No parts => fail
939 	if (!partsInfo) {
940 		stream.seek(startPos);
941 		return false;
942 	}
943 
944 	bool result = false;
945 	// Iterate over all parts
946 	for (Common::Array<SaveContainer::PartInfo>::iterator it = partsInfo->begin();
947 	     it != partsInfo->end(); ++it) {
948 
949 		// Check for the info part
950 		if (it->id == SavePartInfo::kID) {
951 			if (!stream.seek(it->offset))
952 				break;
953 
954 			// Read it
955 			result = info.read(stream);
956 			break;
957 		}
958 	}
959 
960 	stream.seek(startPos);
961 
962 	delete partsInfo;
963 	return result;
964 }
965 
getInfo(const Common::String & fileName,SavePartInfo & info)966 bool SaveReader::getInfo(const Common::String &fileName, SavePartInfo &info) {
967 	Common::InSaveFile *in = openSave(fileName);
968 
969 	if (!in)
970 		return false;
971 
972 	bool result = getInfo(*in, info);
973 
974 	delete in;
975 
976 	return result;
977 }
978 
SaveWriter(uint32 partCount,uint32 slot)979 SaveWriter::SaveWriter(uint32 partCount, uint32 slot) :
980 	SaveContainer(partCount, slot) {
981 }
982 
SaveWriter(uint32 partCount,uint32 slot,const Common::String & fileName)983 SaveWriter::SaveWriter(uint32 partCount, uint32 slot, const Common::String &fileName) :
984 	SaveContainer(partCount, slot), _fileName(fileName) {
985 }
986 
~SaveWriter()987 SaveWriter::~SaveWriter() {
988 }
989 
writePart(uint32 partN,const SavePart * part)990 bool SaveWriter::writePart(uint32 partN, const SavePart *part) {
991 	// Write the part
992 	if (!SaveContainer::writePart(partN, part))
993 		return false;
994 
995 	// If all parts have been written, save and clear
996 	if (hasAllParts() && canSave()) {
997 		if (save()) {
998 			clear();
999 			return true;
1000 		}
1001 
1002 		return false;
1003 	}
1004 
1005 	return true;
1006 }
1007 
save(Common::WriteStream & stream)1008 bool SaveWriter::save(Common::WriteStream &stream) {
1009 	return SaveContainer::write(stream);
1010 }
1011 
save()1012 bool SaveWriter::save() {
1013 	Common::OutSaveFile *out = openSave();
1014 
1015 	if (!out)
1016 		return false;
1017 
1018 	bool success = save(*out);
1019 
1020 	delete out;
1021 
1022 	return success;
1023 }
1024 
canSave() const1025 bool SaveWriter::canSave() const {
1026 	return (!_fileName.empty());
1027 }
1028 
openSave(const Common::String & fileName)1029 Common::OutSaveFile *SaveWriter::openSave(const Common::String &fileName) {
1030 	if (fileName.empty())
1031 		return 0;
1032 
1033 	Common::SaveFileManager *saveMan = g_system->getSavefileManager();
1034 	return saveMan->openForSaving(fileName);
1035 }
1036 
openSave()1037 Common::OutSaveFile *SaveWriter::openSave() {
1038 	return openSave(_fileName);
1039 }
1040 
1041 } // End of namespace Gob
1042