aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/cge2/saveload.cpp123
-rw-r--r--engines/cge2/spare.cpp5
-rw-r--r--engines/cge2/spare.h2
-rw-r--r--engines/cge2/vga13h.cpp54
-rw-r--r--engines/cge2/vga13h.h1
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 {