From 3b1edcdf36fc7a207a70cb28e7dcf7879ea9b7e5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Jan 2015 14:21:57 -0500 Subject: XEEN: Implemented code for 'saving' resources to the loaded savefile --- engines/xeen/files.cpp | 2 +- engines/xeen/files.h | 15 +++++++++++++-- engines/xeen/map.cpp | 21 +++++++++++++++++---- engines/xeen/map.h | 2 ++ engines/xeen/saves.cpp | 25 +++++++++++++++++++++++++ engines/xeen/saves.h | 16 ++++++++++++++++ engines/xeen/scripts.cpp | 40 +++++++++++++++++++++++++--------------- engines/xeen/scripts.h | 7 ++++--- 8 files changed, 103 insertions(+), 25 deletions(-) diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 79387f2e24..8ab1f35fcb 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -32,7 +32,7 @@ namespace Xeen { /** * Hash a given filename to produce the Id that represents it */ -uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) const { +uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) { if (resourceName.empty()) return 0xffff; diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 343aea1e74..7c0817a850 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/file.h" +#include "common/serializer.h" #include "graphics/surface.h" #include "xeen/xsurface.h" @@ -61,6 +62,16 @@ public: void openFile(const Common::String &filename, Common::Archive &archive); }; +class XeenSerializer : public Common::Serializer { +private: + Common::SeekableReadStream *_in; +public: + XeenSerializer(Common::SeekableReadStream *in, Common::WriteStream *out) : + Common::Serializer(in, out), _in(in) {} + + bool finished() const { return _in != nullptr && _in->pos() >= _in->size(); } +}; + /** * Details of a single entry in a CC file index */ @@ -79,14 +90,14 @@ struct CCEntry { * Base Xeen CC file implementation */ class BaseCCArchive : public Common::Archive { -private: - uint16 convertNameToId(const Common::String &resourceName) const; protected: Common::Array _index; void loadIndex(Common::SeekableReadStream *stream); virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; +public: + static uint16 convertNameToId(const Common::String &resourceName); public: BaseCCArchive() {} diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index d07ca2d363..d65e09d5d7 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1042,8 +1042,9 @@ void Map::loadEvents(int mapId) { // Load events Common::String filename = Common::String::format("maze%c%03d.evt", (mapId >= 100) ? 'x' : '0', mapId); - File fEvents(filename); - _events.synchronize(fEvents); + File fEvents(filename, *_vm->_saves); + XeenSerializer sEvents(&fEvents, nullptr); + _events.synchronize(sEvents); fEvents.close(); // Load text data @@ -1052,11 +1053,23 @@ void Map::loadEvents(int mapId) { File fText(filename); _events._text.resize(fText.size()); fText.read(&_events._text[0], fText.size()); - - _events.synchronize(fText); fText.close(); } +void Map::saveMaze() { + int mazeNum = _mazeData[0]._mazeNumber; + if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc)) + return; + + // Save the event data + Common::String filename = Common::String::format("maze%c%03d.evt", + (mazeNum >= 100) ? 'x' : '0', mazeNum); + OutFile fEvents(_vm, filename); + XeenSerializer sEvents(nullptr, &fEvents); + _events.synchronize(sEvents); + fEvents.finalize(); +} + void Map::cellFlagLookup(const Common::Point &pt) { Common::Point pos = pt; int mapId = _vm->_party._mazeId; diff --git a/engines/xeen/map.h b/engines/xeen/map.h index bc1b0245b9..c23b214736 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -350,6 +350,8 @@ public: int mazeLookup(const Common::Point &pt, int directionLayerIndex); void setCellSurfaceFlags(const Common::Point &pt, int bits); + + void saveMaze(); }; } // End of namespace Xeen diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index e6bfa80e09..c2b15106eb 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -29,6 +29,22 @@ namespace Xeen { +OutFile::OutFile(XeenEngine *vm, const Common::String filename) : + _vm(vm), _filename(filename) { +} + +void OutFile::finalize() { + uint16 id = BaseCCArchive::convertNameToId(_filename); + + if (!_vm->_saves->_newData.contains(id)) + _vm->_saves->_newData[id] = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); + + Common::MemoryWriteStreamDynamic &out = _vm->_saves->_newData[id]; + out.write(getData(), size()); +} + +/*------------------------------------------------------------------------*/ + SavesManager::SavesManager(XeenEngine *vm, Party &party, Roster &roster) : BaseCCArchive(), _vm(vm), _party(party), _roster(roster) { SearchMan.add("saves", this, 0, false); @@ -67,6 +83,15 @@ void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) Common::SeekableReadStream *SavesManager::createReadStreamForMember(const Common::String &name) const { CCEntry ccEntry; + // If the given resource has already been perviously "written" to the + // save manager, then return that new resource + uint16 id = BaseCCArchive::convertNameToId(name); + if (_newData.contains(id)) { + Common::MemoryWriteStreamDynamic stream = _newData[id]; + return new Common::MemoryReadStream(stream.getData(), stream.size()); + } + + // Retrieve the resource from the loaded savefile if (getHeaderEntry(name, ccEntry)) { // Open the correct CC entry return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index ed4b80b29d..6b73625c61 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -24,6 +24,7 @@ #define XEEN_SAVES_H #include "common/scummsys.h" +#include "common/memstream.h" #include "common/savefile.h" #include "graphics/surface.h" #include "xeen/party.h" @@ -40,12 +41,27 @@ struct XeenSavegameHeader { int _totalFrames; }; +class XeenEngine; +class SavesManager; + +class OutFile : public Common::MemoryWriteStreamDynamic { +private: + XeenEngine *_vm; + Common::String _filename; +public: + OutFile(XeenEngine *vm, const Common::String filename); + + void finalize(); +}; + class SavesManager: public BaseCCArchive { + friend class OutFile; private: XeenEngine *_vm; Party &_party; Roster &_roster; byte *_data; + Common::HashMap _newData; void load(Common::SeekableReadStream *stream); public: diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ee804317ec..0a864aa2cb 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -27,27 +27,37 @@ namespace Xeen { MazeEvent::MazeEvent() : _direction(DIR_ALL), _line(-1), _opcode(OP_None) { } -void MazeEvent::synchronize(Common::SeekableReadStream &s) { - int len = s.readByte(); - _position.x = s.readByte(); - _position.y = s.readByte(); - _direction = (Direction)s.readByte(); - _line = s.readByte(); - _opcode = (Opcode)s.readByte(); - - for (int i = 0; i < (len - 5); ++i) - _parameters.push_back(s.readByte()); +void MazeEvent::synchronize(Common::Serializer &s) { + int len = 5 + _parameters.size(); + s.syncAsByte(len); + + s.syncAsByte(_position.x); + s.syncAsByte(_position.y); + s.syncAsByte(_direction); + s.syncAsByte(_line); + s.syncAsByte(_opcode); + + len -= 5; + if (s.isLoading()) + _parameters.resize(len); + for (int i = 0; i < len; ++i) + s.syncAsByte(_parameters[i]); } /*------------------------------------------------------------------------*/ -void MazeEvents::synchronize(Common::SeekableReadStream &s) { +void MazeEvents::synchronize(XeenSerializer &s) { MazeEvent e; - clear(); - while (!s.eos()) { - e.synchronize(s); - push_back(e); + if (s.isLoading()) { + clear(); + while (!s.finished()) { + e.synchronize(s); + push_back(e); + } + } else { + for (uint i = 0; i < size(); ++i) + (*this).operator[](i).synchronize(s); } } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 1ab08faa7e..727d37f681 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -25,7 +25,8 @@ #include "common/scummsys.h" #include "common/system.h" -#include "common/stream.h" +#include "common/serializer.h" +#include "xeen/files.h" #include "xeen/party.h" namespace Xeen { @@ -104,14 +105,14 @@ public: public: MazeEvent(); - void synchronize(Common::SeekableReadStream &s); + void synchronize(Common::Serializer &s); }; class MazeEvents : public Common::Array { public: Common::Array _text; public: - void synchronize(Common::SeekableReadStream &s); + void synchronize(XeenSerializer &s); }; } // End of namespace Xeen -- cgit v1.2.3