aboutsummaryrefslogtreecommitdiff
path: root/engines/supernova
diff options
context:
space:
mode:
Diffstat (limited to 'engines/supernova')
-rw-r--r--engines/supernova/rooms.cpp66
-rw-r--r--engines/supernova/rooms.h2
-rw-r--r--engines/supernova/state.cpp93
-rw-r--r--engines/supernova/state.h2
-rw-r--r--engines/supernova/supernova.cpp79
-rw-r--r--engines/supernova/supernova.h8
6 files changed, 250 insertions, 0 deletions
diff --git a/engines/supernova/rooms.cpp b/engines/supernova/rooms.cpp
index cfccd11b58..a767156d0c 100644
--- a/engines/supernova/rooms.cpp
+++ b/engines/supernova/rooms.cpp
@@ -27,6 +27,72 @@
namespace Supernova {
+bool Room::serialize(Common::WriteStream *out) {
+ if (out->err())
+ return false;
+
+ out->writeByte(_id);
+ for (int i = 0; i < kMaxSection; ++i)
+ out->writeByte(_shown[i]);
+
+ int numObjects = 0;
+ while ((_objectState[numObjects]._id != INVALIDOBJECT) && (numObjects < kMaxObject))
+ ++numObjects;
+ out->writeByte(numObjects);
+
+ for (int i = 0; i < numObjects; ++i) {
+ out->writeSint16LE(_objectState[i]._name.size() + 1);
+ out->writeString(_objectState[i]._name.c_str());
+ out->writeSint16LE(_objectState[i]._description.size() + 1);
+ out->writeString(_objectState[i]._description.c_str());
+ out->writeByte(_objectState[i]._roomId);
+ out->writeByte(_objectState[i]._id);
+ out->writeSint16LE(_objectState[i]._type);
+ out->writeByte(_objectState[i]._click);
+ out->writeByte(_objectState[i]._click2);
+ out->writeByte(_objectState[i]._section);
+ out->writeByte(_objectState[i]._exitRoom);
+ out->writeByte(_objectState[i]._direction);
+ }
+
+ out->writeByte(_seen);
+
+ return !out->err();
+}
+
+bool Room::deserialize(Common::ReadStream *in) {
+ if (in->err())
+ return false;
+
+ in->readByte();
+ for (int i = 0; i < kMaxSection; ++i)
+ _shown[i] = in->readByte();
+
+ int numObjects = in->readByte();
+ int bufferSize = 0;
+ char stringBuffer[256];
+ for (int i = 0; i < numObjects; ++i) {
+ bufferSize = in->readSint16LE();
+ in->read(stringBuffer, bufferSize > 256 ? 256 : bufferSize);
+ _objectState[i]._name = stringBuffer;
+ bufferSize = in->readSint16LE();
+ in->read(stringBuffer, bufferSize > 256 ? 256 : bufferSize);
+ _objectState[i]._description = stringBuffer;
+ _objectState[i]._roomId = in->readByte();
+ _objectState[i]._id = static_cast<ObjectID>(in->readByte());
+ _objectState[i]._type = static_cast<ObjectType>(in->readSint16LE());
+ _objectState[i]._click = in->readByte();
+ _objectState[i]._click2 = in->readByte();
+ _objectState[i]._section = in->readByte();
+ _objectState[i]._exitRoom = static_cast<RoomID>(in->readByte());
+ _objectState[i]._direction = in->readByte();
+ }
+
+ _seen = in->readByte();
+
+ return !in->err();
+}
+
void Intro::onEntrance() {
}
diff --git a/engines/supernova/rooms.h b/engines/supernova/rooms.h
index b3956b8a6d..a5895fa8a8 100644
--- a/engines/supernova/rooms.h
+++ b/engines/supernova/rooms.h
@@ -70,6 +70,8 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2) {
return false;
}
+ virtual bool serialize(Common::WriteStream *out);
+ virtual bool deserialize(Common::ReadStream *in);
protected:
int _fileNumber;
diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp
index 5b5af20e12..5756034a87 100644
--- a/engines/supernova/state.cpp
+++ b/engines/supernova/state.cpp
@@ -22,11 +22,104 @@
#include "common/system.h"
#include "graphics/palette.h"
+#include "gui/message.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
namespace Supernova {
+bool GameManager::serialize(Common::WriteStream *out) {
+ if (out->err())
+ return false;
+
+ // GameState
+ out->writeSint32LE(_state._time);
+ out->writeSint32LE(_state._timeSleep);
+ out->writeSint32LE(_state._timeAlarm);
+ out->writeSint32LE(_state._eventTime);
+ out->writeSint32LE(_state._arrivalDaysLeft);
+ out->writeSint32LE(_state._shipEnergyDaysLeft);
+ out->writeSint32LE(_state._landingModuleEnergyDaysLeft);
+ out->writeUint16LE(_state._greatFlag);
+ out->writeSint16LE(_state._timeRobot);
+ out->writeSint16LE(_state._money);
+ out->writeByte(_state._coins);
+ out->writeByte(_state._shoes);
+ out->writeByte(_state._destination);
+ out->writeByte(_state._language);
+ out->writeByte(_state._corridorSearch);
+ out->writeByte(_state._alarmOn);
+ out->writeByte(_state._terminalStripConnected);
+ out->writeByte(_state._terminalStripWire);
+ out->writeByte(_state._cableConnected);
+ out->writeByte(_state._powerOff);
+ out->writeByte(_state._dream);
+
+ // Inventory
+ out->writeSByte(_inventory.getSize());
+ out->writeSByte(_inventoryScroll);
+ for (int i = 0; i < _inventory.getSize(); ++i) {
+ Object *objectStateBegin = _rooms[_inventory.get(i)->_roomId]->getObject(0);
+ byte objectIndex = _inventory.get(i) - objectStateBegin;
+ out->writeByte(_inventory.get(i)->_roomId);
+ out->writeByte(objectIndex);
+ }
+
+ // Rooms
+ for (int i = 0; i < kRoomsNum; ++i) {
+ _rooms[i]->serialize(out);
+ }
+
+ return !out->err();
+}
+
+
+bool GameManager::deserialize(Common::ReadStream *in) {
+ if (in->err()) {
+ return false;
+ }
+
+ // GameState
+ _state._time = in->readSint32LE();
+ _state._timeSleep = in->readSint32LE();
+ _state._timeAlarm = in->readSint32LE();
+ _state._eventTime = in->readSint32LE();
+ _state._arrivalDaysLeft = in->readSint32LE();
+ _state._shipEnergyDaysLeft = in->readSint32LE();
+ _state._landingModuleEnergyDaysLeft = in->readSint32LE();
+ _state._greatFlag = in->readUint16LE();
+ _state._timeRobot = in->readSint16LE();
+ _state._money = in->readSint16LE();
+ _state._coins = in->readByte();
+ _state._shoes = in->readByte();
+ _state._destination = in->readByte();
+ _state._language = in->readByte();
+ _state._corridorSearch = in->readByte();
+ _state._alarmOn = in->readByte();
+ _state._terminalStripConnected = in->readByte();
+ _state._terminalStripWire = in->readByte();
+ _state._cableConnected = in->readByte();
+ _state._powerOff = in->readByte();
+ _state._dream = in->readByte();
+
+ // Inventory
+ int inventorySize = in->readSByte();
+ _inventoryScroll = in->readSByte();
+ _inventory.clear();
+ for (int i = 0; i < inventorySize; ++i) {
+ RoomID objectRoom = static_cast<RoomID>(in->readByte());
+ int objectIndex = in->readByte();
+ _inventory.add(*_rooms[objectRoom]->getObject(objectIndex));
+ }
+
+ // Rooms
+ for (int i = 0; i < kRoomsNum; ++i) {
+ _rooms[i]->deserialize(in);
+ }
+
+ return !in->err();
+}
+
Inventory::Inventory()
: _numObjects(0)
{}
diff --git a/engines/supernova/state.h b/engines/supernova/state.h
index eb7c1e2d2d..0f6efc05e7 100644
--- a/engines/supernova/state.h
+++ b/engines/supernova/state.h
@@ -101,6 +101,8 @@ public:
void processInput(Common::KeyState &state);
void processInput();
void executeRoom();
+ bool serialize(Common::WriteStream *out);
+ bool deserialize(Common::ReadStream *in);
SupernovaEngine *_vm;
Common::KeyState _key;
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index e1abc006ad..f3678de5a1 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -110,6 +110,8 @@ SupernovaEngine::SupernovaEngine(OSystem *syst)
, _screenWidth(320)
, _screenHeight(200)
, _messageDisplayed(false)
+ , _allowLoadGame(true)
+ , _allowSaveGame(false)
{
// const Common::FSNode gameDataDir(ConfMan.get("path"));
// SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
@@ -211,6 +213,10 @@ bool SupernovaEngine::hasFeature(EngineFeature f) const {
switch (f) {
case kSupportsRTL:
return true;
+ case kSupportsLoadingDuringRuntime:
+ return true;
+ case kSupportsSavingDuringRuntime:
+ return true;
default:
return false;
}
@@ -787,6 +793,79 @@ Common::MemoryReadStream *SupernovaEngine::convertToMod(const char *filename, in
return new Common::MemoryReadStream(buffer.getData(), buffer.size());
}
+bool SupernovaEngine::canLoadGameStateCurrently() {
+ return _allowLoadGame;
+}
+
+Common::Error SupernovaEngine::loadGameState(int slot) {
+ return (loadGame(slot) ? Common::kNoError : Common::kWritingFailed);
+}
+
+bool SupernovaEngine::canSaveGameStateCurrently() {
+ return _allowSaveGame;
+}
+
+Common::Error SupernovaEngine::saveGameState(int slot, const Common::String &desc) {
+ return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed);
+}
+
+bool SupernovaEngine::loadGame(int slot) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Load game:", "Load:", false);
+ int loadGameSlot = dialog->runModalWithCurrentTarget();
+ delete dialog;
+
+ if (loadGameSlot < 0 || loadGameSlot > 10)
+ return false;
+
+ Common::String filename = Common::String::format("msn_save.%02d", loadGameSlot);
+// Common::InSaveFile *savefile = _saveFileMan->openForLoading(filename);
+ Common::InSaveFile *savefile = _saveFileMan->openRawFile(filename);
+ if (!savefile)
+ return false;
+
+ int descriptionSize = savefile->readSint16LE();
+ savefile->skip(descriptionSize);
+ savefile->skip(6);
+// Graphics::skipThumbnail(*savefile);
+ _gm->deserialize(savefile);
+
+ delete savefile;
+
+ return true;
+}
+
+bool SupernovaEngine::saveGame(int slot, const Common::String &description) {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
+ int saveGameSlot = dialog->runModalWithCurrentTarget();
+ Common::String saveGameDescription = dialog->getResultString();
+ delete dialog;
+
+ if (saveGameSlot < 0 || saveGameSlot > 10)
+ return false;
+
+ Common::String filename = Common::String::format("msn_save.%02d", saveGameSlot);
+ Common::OutSaveFile *savefile = _saveFileMan->openForSaving(filename, false);
+ if (!savefile)
+ return false;
+
+ TimeDate currentDate;
+ _system->getTimeAndDate(currentDate);
+ uint32 saveDate = (currentDate.tm_mday & 0xFF) << 24 | ((currentDate.tm_mon + 1) & 0xFF) << 16 | ((currentDate.tm_year + 1900) & 0xFFFF);
+ uint16 saveTime = (currentDate.tm_hour & 0xFF) << 8 | ((currentDate.tm_min) & 0xFF);
+
+ savefile->writeSint16LE(saveGameDescription.size() + 1);
+ savefile->write(saveGameDescription.c_str(), saveGameDescription.size() + 1);
+ savefile->writeUint32LE(saveDate);
+ savefile->writeUint16LE(saveTime);
+// Graphics::saveThumbnail(*savefile);
+ _gm->serialize(savefile);
+
+ savefile->finalize();
+ delete savefile;
+
+ return true;
+}
+
ScreenBufferStack::ScreenBufferStack()
: _last(_buffer) {
diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h
index 1a81e0f17a..4327ba1d7d 100644
--- a/engines/supernova/supernova.h
+++ b/engines/supernova/supernova.h
@@ -95,6 +95,8 @@ public:
Common::Event _event;
int _screenWidth;
int _screenHeight;
+ bool _allowLoadGame;
+ bool _allowSaveGame;
byte _imageIndex;
byte _sectionIndex;
@@ -133,9 +135,15 @@ public:
void renderBox(int x, int y, int width, int height, byte color);
void setColor63(byte value);
void command_print();
+ bool loadGame(int slot);
+ bool saveGame(int slot, const Common::String &description);
Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
+ virtual Common::Error loadGameState(int slot);
+ virtual bool canLoadGameStateCurrently();
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual bool canSaveGameStateCurrently();
virtual bool hasFeature(EngineFeature f) const;
virtual void pauseEngineIntern(bool pause);
};