diff options
-rw-r--r-- | engines/cge2/saveload.cpp | 123 | ||||
-rw-r--r-- | engines/cge2/spare.cpp | 5 | ||||
-rw-r--r-- | engines/cge2/spare.h | 2 | ||||
-rw-r--r-- | engines/cge2/vga13h.cpp | 54 | ||||
-rw-r--r-- | engines/cge2/vga13h.h | 1 |
5 files changed, 153 insertions, 32 deletions
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp index ac059e5d8f..971b044e35 100644 --- a/engines/cge2/saveload.cpp +++ b/engines/cge2/saveload.cpp @@ -36,9 +36,13 @@ #include "cge2/events.h" #include "cge2/snail.h" #include "cge2/hero.h" +#include "cge2/text.h" namespace CGE2 { +#define kSavegameCheckSum (1997 + _now + _music + kWorldHeight) +#define kBadSVG 99 + struct SavegameHeader { uint8 version; Common::String saveName; @@ -123,11 +127,6 @@ SaveStateDescriptor CGE2MetaEngine::querySaveMetaInfos(const char *target, int s desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay); desc.setSaveTime(header.saveHour, header.saveMinutes); - // Slot 0 is used for the 'automatic save on exit' save in Soltys, thus - // we prevent it from being deleted or overwritten by accident. - desc.setDeletableFlag(slot != 0); - desc.setWriteProtectedFlag(slot == 0); - return desc; } } @@ -185,10 +184,122 @@ bool CGE2Engine::canLoadGameStateCurrently() { } Common::Error CGE2Engine::saveGameState(int slot, const Common::String &desc) { - warning("STUB: CGE2Engine::saveGameState()"); + // Set up the serializer + Common::String slotName = generateSaveName(slot); + Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(slotName); + + // Write out the ScummVM savegame header + SavegameHeader header; + header.saveName = desc; + header.version = kSavegameVersion; + writeSavegameHeader(saveFile, header); + + // Write out the data of the savegame + syncGame(NULL, saveFile); + + // Finish writing out game data + saveFile->finalize(); + delete saveFile; + return Common::kNoError; } +/** +* Support method that generates a savegame name +* @param slot Slot number +*/ +Common::String CGE2Engine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +void CGE2Engine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header) { + // Write out a savegame header + out->write(kSavegameStr, kSavegameStrSize + 1); + + out->writeByte(kSavegameVersion); + + // Write savegame name + out->write(header.saveName.c_str(), header.saveName.size() + 1); + + // Get the active palette + uint8 thumbPalette[256 * 3]; + g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + Graphics::Surface *s = _vga->_page[0]; + ::createThumbnail(thumb, (const byte *)s->getPixels(), kScrWidth, kScrHeight, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + thumb->free(); + delete thumb; + + // 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); +} + +void CGE2Engine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) { + Common::Serializer s(readStream, writeStream); + + // Synchronise header data + syncHeader(s); + + if (s.isSaving()) { + for (int i = 0; i < kSceneMax; i++) + _eyeTab[i]->sync(s); + + _spare->sync(s); + + // The references of the items in the heroes pockets: + for (int i = 0; i < 2; i++) { + for (int j = 0; j < kPocketMax; j++) { + Sprite *spr = _heroTab[i]->_pocket[j]; + int ref = (spr) ? spr->_ref : -1; + s.syncAsSint16LE(ref); + } + } + + for (int i = 0; i < kMaxPoint; i++) + _point[i]->sync(s); + } else { + // Loading game + } +} + +void CGE2Engine::syncHeader(Common::Serializer &s) { + s.syncAsUint16LE(_now); + s.syncAsUint16LE(_sex); + s.syncAsUint16LE(_music); + s.syncAsUint16LE(_waitSeq); + s.syncAsUint16LE(_waitRef); + s.syncAsUint16LE(_sayCap); + s.syncAsUint16LE(_sayVox); + for (int i = 0; i < 4; i++) + s.syncAsUint16LE(_flag[i]); + + if (s.isLoading()) { + // Reset scene values + //initSceneValues(); + } + + if (s.isSaving()) { + // Write checksum + int checksum = kSavegameCheckSum; + s.syncAsUint16LE(checksum); + } else { + // Read checksum and validate it + uint16 checksum = 0; + s.syncAsUint16LE(checksum); + if (checksum != kSavegameCheckSum) + error("%s", _text->getText(kBadSVG)); + } +} + Common::Error CGE2Engine::loadGameState(int slot) { warning("STUB: CGE2Engine::loadGameState()"); return Common::kNoError; diff --git a/engines/cge2/spare.cpp b/engines/cge2/spare.cpp index 8382310e1b..76f0065196 100644 --- a/engines/cge2/spare.cpp +++ b/engines/cge2/spare.cpp @@ -29,8 +29,9 @@ namespace CGE2 { -void Spare::synchronize() { - warning("STUB: Spare::Load"); +void Spare::sync(Common::Serializer &s) { + for (int i = 0; i < _container.size(); i++) + _container[i]->sync(s); } void Spare::clear() { diff --git a/engines/cge2/spare.h b/engines/cge2/spare.h index 77bdb3319f..7dc6ce60f5 100644 --- a/engines/cge2/spare.h +++ b/engines/cge2/spare.h @@ -46,7 +46,7 @@ public: void dispose(Sprite *spr); void dispose(int ref); void dispose(); - void synchronize(); + void sync(Common::Serializer &s); uint16 count() { return _container.size(); } void clear(); }; diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp index 29ee5c8b44..a181621008 100644 --- a/engines/cge2/vga13h.cpp +++ b/engines/cge2/vga13h.cpp @@ -39,6 +39,25 @@ namespace CGE2 { +void V3D::sync(Common::Serializer &s) { + int pos = 0; + if (s.isLoading()) { + s.syncAsSint16LE(pos); + _x = FXP(pos); + s.syncAsSint16LE(pos); + _y = FXP(pos); + s.syncAsSint16LE(pos); + _z = FXP(pos); + } else { + pos = _x.trunc(); + s.syncAsUint16LE(pos); + pos = _y.trunc(); + s.syncAsUint16LE(pos); + pos = _z.trunc(); + s.syncAsByte(pos); + } +} + Seq *getConstantSeq(bool seqFlag) { const Seq seq1[] = { { 0, 0, 0, 0, 0, 0 } }; const Seq seq2[] = { { 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0 } }; @@ -675,10 +694,6 @@ BitmapPtr Sprite::ghost() { } void Sprite::sync(Common::Serializer &s) { - uint16 unused = 0; - - s.syncAsUint16LE(unused); - s.syncAsUint16LE(unused); // _ext s.syncAsUint16LE(_ref); s.syncAsByte(_scene); @@ -723,31 +738,24 @@ void Sprite::sync(Common::Serializer &s) { s.syncAsUint16LE(flags); } - int pos = 0; - if (s.isLoading()) { - s.syncAsSint16LE(pos); - _pos3D._x = FXP(pos, 0); - s.syncAsSint16LE(pos); - _pos3D._y = pos; - s.syncAsSint16LE(pos); - _pos3D._z = pos; - } else { - pos = _pos3D._x.trunc(); - s.syncAsUint16LE(pos); - pos = _pos3D._y.trunc(); - s.syncAsUint16LE(pos); - pos = _pos3D._z.trunc(); - s.syncAsByte(pos); - } + s.syncAsSint16LE(_pos2D.x); + s.syncAsSint16LE(_pos2D.y); + + _pos3D.sync(s); + + s.syncAsSint16LE(_siz.x); + s.syncAsSint16LE(_siz.y); s.syncAsUint16LE(_time); + for (int i = 0; i < kActions; i++){ + s.syncAsSint16LE(_actionCtrl->_ptr); + s.syncAsSint16LE(_actionCtrl->_cnt); + } s.syncAsSint16LE(_seqPtr); + s.syncAsSint16LE(_seqCnt); s.syncAsUint16LE(_shpCnt); s.syncBytes((byte *)&_file[0], 9); _file[8] = '\0'; - - s.syncAsUint16LE(unused); // _prev - s.syncAsUint16LE(unused); // _next } Queue::Queue(bool show) : _head(NULL), _tail(NULL) { diff --git a/engines/cge2/vga13h.h b/engines/cge2/vga13h.h index 6c68c8cf07..c42b7a746e 100644 --- a/engines/cge2/vga13h.h +++ b/engines/cge2/vga13h.h @@ -132,6 +132,7 @@ public: bool operator!=(const V3D &p) const { return _x != p._x || _y != p._y || _z != p._z; } V3D& operator+=(const V3D &x) { return *this = *this + x; } V3D& operator-=(const V3D &x) { return *this = *this - x; } + void sync(Common::Serializer &s); }; class V2D : public Common::Point { |