XEEN: Implemented code for 'saving' resources to the loaded savefile

This commit is contained in:
Paul Gilbert 2015-01-11 14:21:57 -05:00
parent 0b5f79afb7
commit 3b1edcdf36
8 changed files with 102 additions and 24 deletions

View File

@ -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;

View File

@ -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<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() {}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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<uint16, Common::MemoryWriteStreamDynamic > _newData;
void load(Common::SeekableReadStream *stream);
public:

View File

@ -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();
void MazeEvent::synchronize(Common::Serializer &s) {
int len = 5 + _parameters.size();
s.syncAsByte(len);
for (int i = 0; i < (len - 5); ++i)
_parameters.push_back(s.readByte());
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);
}
}

View File

@ -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<MazeEvent> {
public:
Common::Array<byte> _text;
public:
void synchronize(Common::SeekableReadStream &s);
void synchronize(XeenSerializer &s);
};
} // End of namespace Xeen