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