Skip to content

Commit

Permalink
XEEN: Implemented code for 'saving' resources to the loaded savefile
Browse files Browse the repository at this point in the history
  • Loading branch information
dreammaster committed Jan 11, 2015
1 parent 0b5f79a commit 3b1edcd
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 25 deletions.
2 changes: 1 addition & 1 deletion engines/xeen/files.cpp
Expand Up @@ -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;

Expand Down
15 changes: 13 additions & 2 deletions engines/xeen/files.h
Expand Up @@ -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"

Expand Down Expand Up @@ -61,6 +62,16 @@ class File : public Common::File {
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
*/
Expand All @@ -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<CCEntry> _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() {}

Expand Down
21 changes: 17 additions & 4 deletions engines/xeen/map.cpp
Expand Up @@ -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
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions engines/xeen/map.h
Expand Up @@ -350,6 +350,8 @@ class Map {
int mazeLookup(const Common::Point &pt, int directionLayerIndex);

void setCellSurfaceFlags(const Common::Point &pt, int bits);

void saveMaze();
};

} // End of namespace Xeen
Expand Down
25 changes: 25 additions & 0 deletions engines/xeen/saves.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions engines/xeen/saves.h
Expand Up @@ -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"
Expand All @@ -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<uint16, Common::MemoryWriteStreamDynamic > _newData;

void load(Common::SeekableReadStream *stream);
public:
Expand Down
40 changes: 25 additions & 15 deletions engines/xeen/scripts.cpp
Expand Up @@ -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);
}
}

Expand Down
7 changes: 4 additions & 3 deletions engines/xeen/scripts.h
Expand Up @@ -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 {
Expand Down Expand Up @@ -104,14 +105,14 @@ class MazeEvent {
public:
MazeEvent();

void synchronize(Common::SeekableReadStream &s);
void synchronize(Common::Serializer &s);
};

class MazeEvents : public Common::Array<MazeEvent> {
public:
Common::Array<byte> _text;
public:
void synchronize(Common::SeekableReadStream &s);
void synchronize(XeenSerializer &s);
};

} // End of namespace Xeen
Expand Down

0 comments on commit 3b1edcd

Please sign in to comment.