diff options
author | Joseph-Eugene Winzer | 2017-08-29 01:27:07 +0200 |
---|---|---|
committer | Thierry Crozat | 2018-01-23 01:53:31 +0000 |
commit | 3f68cda2d7889d21a764e39f1c8ce924609c919e (patch) | |
tree | d375d3e89abf46997c51bda0bd8aa304cc91a408 /engines/supernova | |
parent | ef14dfb7c301b4210770e95955b27e765b3353b2 (diff) | |
download | scummvm-rg350-3f68cda2d7889d21a764e39f1c8ce924609c919e.tar.gz scummvm-rg350-3f68cda2d7889d21a764e39f1c8ce924609c919e.tar.bz2 scummvm-rg350-3f68cda2d7889d21a764e39f1c8ce924609c919e.zip |
SUPERNOVA: Implements de-/serialization
WIP. It is currently broken.
Diffstat (limited to 'engines/supernova')
-rw-r--r-- | engines/supernova/rooms.cpp | 66 | ||||
-rw-r--r-- | engines/supernova/rooms.h | 2 | ||||
-rw-r--r-- | engines/supernova/state.cpp | 93 | ||||
-rw-r--r-- | engines/supernova/state.h | 2 | ||||
-rw-r--r-- | engines/supernova/supernova.cpp | 79 | ||||
-rw-r--r-- | engines/supernova/supernova.h | 8 |
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); }; |