Skip to content

Commit

Permalink
XEEN: Add saving of map/event data when the map is changed
Browse files Browse the repository at this point in the history
  • Loading branch information
dreammaster committed Dec 27, 2017
1 parent 6437ca1 commit f8f2058
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 54 deletions.
12 changes: 11 additions & 1 deletion engines/xeen/files.cpp
Expand Up @@ -436,11 +436,21 @@ void SaveArchive::reset(CCArchive *src) {

/*------------------------------------------------------------------------*/

OutFile::OutFile(const Common::String filename) :
OutFile::OutFile(const Common::String &filename) :
_filename(filename), _backingStream(DisposeAfterUse::YES) {
_archive = File::_currentSave;
}

OutFile::OutFile(const Common::String &filename, SaveArchive *archive) :
_filename(filename), _archive(archive), _backingStream(DisposeAfterUse::YES) {
}

OutFile::OutFile(const Common::String &filename, int ccMode) :
_filename(filename), _backingStream(DisposeAfterUse::YES) {
g_vm->_files->setGameCc(ccMode);
_archive = File::_currentSave;
}

uint32 OutFile::write(const void *dataPtr, uint32 dataSize) {
return _backingStream.write(dataPtr, dataSize);
}
Expand Down
16 changes: 15 additions & 1 deletion engines/xeen/files.h
Expand Up @@ -274,18 +274,32 @@ class SaveArchive : public BaseCCArchive {
virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
};

/**
* Provides an interface to updating files within the in-memory save state
*/
class OutFile : public Common::WriteStream {
private:
SaveArchive *_archive;
Common::String _filename;
Common::MemoryWriteStreamDynamic _backingStream;
public:
OutFile(const Common::String filename);
OutFile(const Common::String &filename);
OutFile(const Common::String &filename, SaveArchive *archive);
OutFile(const Common::String &filename, int ccMode);

/**
* Finishes any pending writes, pushing out the written data
*/
void finalize();

/**
* Writes data
*/
uint32 write(const void *dataPtr, uint32 dataSize) override;

/**
* Returns the current position
*/
int32 pos() const override;
};

Expand Down
156 changes: 107 additions & 49 deletions engines/xeen/map.cpp
Expand Up @@ -518,11 +518,11 @@ void SurroundingMazes::clear() {
_west = 0;
}

void SurroundingMazes::synchronize(Common::SeekableReadStream &s) {
_north = s.readUint16LE();
_east = s.readUint16LE();
_south = s.readUint16LE();
_west = s.readUint16LE();
void SurroundingMazes::synchronize(XeenSerializer &s) {
s.syncAsUint16LE(_north);
s.syncAsUint16LE(_east);
s.syncAsUint16LE(_south);
s.syncAsUint16LE(_west);
}

int &SurroundingMazes::operator[](int idx) {
Expand Down Expand Up @@ -551,15 +551,15 @@ MazeDifficulties::MazeDifficulties() {
_chance2Run = -1;
}

void MazeDifficulties::synchronize(Common::SeekableReadStream &s) {
_wallNoPass = s.readByte();
_surfaceNoPass = s.readByte();
_unlockDoor = s.readByte();
_unlockBox = s.readByte();
_bashDoor = s.readByte();
_bashGrate = s.readByte();
_bashWall = s.readByte();
_chance2Run = s.readByte();
void MazeDifficulties::synchronize(XeenSerializer &s) {
s.syncAsByte(_wallNoPass);
s.syncAsByte(_surfaceNoPass);
s.syncAsByte(_unlockDoor);
s.syncAsByte(_unlockBox);
s.syncAsByte(_bashDoor);
s.syncAsSint8(_bashGrate);
s.syncAsSint8(_bashWall);
s.syncAsSint8(_chance2Run);
}

/*------------------------------------------------------------------------*/
Expand Down Expand Up @@ -587,42 +587,48 @@ void MazeData::clear() {
_mazeId = 0;
}

void MazeData::synchronize(Common::SeekableReadStream &s) {
void MazeData::synchronize(XeenSerializer &s) {
byte b;

for (int y = 0; y < MAP_HEIGHT; ++y) {
for (int x = 0; x < MAP_WIDTH; ++x)
_wallData[y][x]._data = s.readUint16LE();
s.syncAsUint16LE(_wallData[y][x]._data);
}
for (int y = 0; y < MAP_HEIGHT; ++y) {
for (int x = 0; x < MAP_WIDTH; ++x) {
byte b = s.readByte();
_cells[y][x]._surfaceId = b & 7;
_cells[y][x]._flags = b & 0xF8;
if (s.isLoading()) {
s.syncAsByte(b);
_cells[y][x]._surfaceId = b & 7;
_cells[y][x]._flags = b & 0xF8;
} else {
b = (_cells[y][x]._surfaceId & 7) | (_cells[y][x]._flags & 0xf8);
s.syncAsByte(b);
}
}
}

_mazeNumber = s.readUint16LE();
s.syncAsUint16LE(_mazeNumber);
_surroundingMazes.synchronize(s);
_mazeFlags = s.readUint16LE();
_mazeFlags2 = s.readUint16LE();
s.syncAsUint16LE(_mazeFlags);
s.syncAsUint16LE(_mazeFlags2);

for (int i = 0; i < 16; ++i)
_wallTypes[i] = s.readByte();
s.syncAsByte(_wallTypes[i]);
for (int i = 0; i < 16; ++i)
_surfaceTypes[i] = s.readByte();
s.syncAsByte(_surfaceTypes[i]);

_floorType = s.readByte();
_runPosition.x = s.readByte();
s.syncAsByte(_floorType);
s.syncAsByte(_runPosition.x);
_difficulties.synchronize(s);
_runPosition.y = s.readByte();
_trapDamage = s.readByte();
_wallKind = s.readByte();
_tavernTips = s.readByte();
s.syncAsByte(_runPosition.y);
s.syncAsByte(_trapDamage);
s.syncAsByte(_wallKind);
s.syncAsByte(_tavernTips);

Common::Serializer ser(&s, nullptr);
for (int y = 0; y < MAP_HEIGHT; ++y)
File::syncBitFlags(ser, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]);
File::syncBitFlags(s, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]);
for (int y = 0; y < MAP_HEIGHT; ++y)
File::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]);
File::syncBitFlags(s, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]);
}

void MazeData::setAllTilesStepped() {
Expand Down Expand Up @@ -724,19 +730,19 @@ void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData &monsterData)
for (uint i = 0; i < 16; ++i) {
b = (i >= _objectSprites.size()) ? 0xff : _objectSprites[i]._spriteId;
s.syncAsByte(b);
if (b != 0xff)
if (s.isLoading() && b != 0xff)
_objectSprites.push_back(SpriteResourceEntry(b));
}
for (uint i = 0; i < 16; ++i) {
b = (i >= _monsterSprites.size()) ? 0xff : _monsterSprites[i]._spriteId;
s.syncAsByte(b);
if (b != 0xff)
if (s.isLoading() && b != 0xff)
_monsterSprites.push_back(SpriteResourceEntry(b));
}
for (uint i = 0; i < 16; ++i) {
b = (i >= _wallItemSprites.size()) ? 0xff : _wallItemSprites[i]._spriteId;
s.syncAsByte(b);
if (b != 0xff)
if (s.isLoading() && b != 0xff)
_wallItemSprites.push_back(SpriteResourceEntry(b));
}

Expand Down Expand Up @@ -958,6 +964,7 @@ void Map::load(int mapId) {
intf._objNumber = 0;
party._stepped = true;
party._mazeId = mapId;
saveMaze();
events.clearEvents();

_sideObjects = 1;
Expand Down Expand Up @@ -1041,7 +1048,8 @@ void Map::load(int mapId) {
Common::String datName = Common::String::format("maze%c%03d.dat",
(mapId >= 100) ? 'x' : '0', mapId);
File datFile(datName);
mazeDataP->synchronize(datFile);
XeenSerializer datSer(&datFile, nullptr);
mazeDataP->synchronize(datSer);
datFile.close();

if (isDarkCc && mapId == 50)
Expand Down Expand Up @@ -1402,26 +1410,76 @@ void Map::loadEvents(int mapId) {
fText.close();
}

void Map::saveMaze() {
int mazeNum = _mazeData[0]._mazeNumber;
if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc))
return;

// Save the event data
void Map::saveEvents() {
// Save eents
int mapId = _mazeData[0]._mazeId;
Common::String filename = Common::String::format("maze%c%03d.evt",
(mazeNum >= 100) ? 'x' : '0', mazeNum);
(mapId >= 100) ? 'x' : '0', mapId);
OutFile fEvents(filename);
XeenSerializer sEvents(nullptr, &fEvents);
_events.synchronize(sEvents);
fEvents.finalize();
}

// Save the maze MOB file
filename = Common::String::format("maze%c%03d.mob",
(mazeNum >= 100) ? 'x' : '0', mazeNum);
void Map::saveMonsters() {
int mapId = _mazeData[0]._mazeId;
Common::String filename = Common::String::format("maze%c%03d.mob",
(mapId >= 100) ? 'x' : '0', mapId);
OutFile fMob(filename);
XeenSerializer sMob(nullptr, &fEvents);
XeenSerializer sMob(nullptr, &fMob);
_mobData.synchronize(sMob, _monsterData);
fEvents.finalize();
fMob.finalize();
}

void Map::saveMap() {
FileManager &files = *g_vm->_files;
Party &party = *g_vm->_party;
int mapId = _mazeData[0]._mazeId;
if (!files._isDarkCc && mapId == 85)
return;

// Save the primary maze
Common::String datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId);
OutFile datFile(datName);
XeenSerializer datSer(nullptr, &datFile);
_mazeData[0].synchronize(datSer);
datFile.finalize();

if (!files._isDarkCc && mapId == 15) {
MazeMonster &mon0 = _mobData._monsters[0];
MazeMonster &mon1 = _mobData._monsters[1];
MazeMonster &mon2 = _mobData._monsters[2];
if ((mon0._position.x > 31 || mon0._position.y > 31) ||
(mon1._position.x > 31 || mon1._position.y > 31) ||
(mon2._position.x > 31 || mon2._position.y > 31)) {
party._gameFlags[0][56] = true;
}
}

if (!_isOutdoors) {
// Iterate through the surrounding mazes
for (int mazeIndex = 1; mazeIndex < 9; ++mazeIndex) {
mapId = _mazeData[_mazeDataIndex]._mazeId;
if (mapId == 0)
continue;

datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId);
OutFile datFile2(datName);
XeenSerializer datSer2(nullptr, &datFile2);
_mazeData[mazeIndex].synchronize(datSer2);
datFile2.finalize();
}
}
}

void Map::saveMaze() {
int mazeNum = _mazeData[0]._mazeNumber;
if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc))
return;

saveEvents();
saveMap();
saveMonsters();
}

void Map::cellFlagLookup(const Common::Point &pt) {
Expand Down
31 changes: 28 additions & 3 deletions engines/xeen/map.h
Expand Up @@ -27,6 +27,7 @@
#include "common/array.h"
#include "common/rect.h"
#include "xeen/combat.h"
#include "xeen/files.h"
#include "xeen/party.h"
#include "xeen/scripts.h"
#include "xeen/sprites.h"
Expand Down Expand Up @@ -114,7 +115,7 @@ class SurroundingMazes {

void clear();

void synchronize(Common::SeekableReadStream &s);
void synchronize(XeenSerializer &s);

int &operator[](int idx);
};
Expand All @@ -132,7 +133,10 @@ class MazeDifficulties {
public:
MazeDifficulties();

void synchronize(Common::SeekableReadStream &s);
/**
* Synchronizes data for the item
*/
void synchronize(XeenSerializer &s);
};

enum MazeFlags {
Expand Down Expand Up @@ -208,7 +212,10 @@ class MazeData {

void clear();

void synchronize(Common::SeekableReadStream &s);
/**
* Synchronize data for the maze data
*/
void synchronize(XeenSerializer &s);

/**
* Flags all tiles for the map as having been stepped on
Expand Down Expand Up @@ -395,6 +402,21 @@ class Map {
* Load the events for a new map
*/
void loadEvents(int mapId);

/**
* Save the events for a map
*/
void saveEvents();

/**
* Save the monster data for a map
*/
void saveMonsters();

/**
* Save the map data
*/
void saveMap();
public:
Common::String _mazeName;
bool _isOutdoors;
Expand Down Expand Up @@ -433,6 +455,9 @@ class Map {

void setWall(const Common::Point &pt, Direction dir, int v);

/**
* Saves all changeable maze data to the in-memory save state
*/
void saveMaze();

int getCell(int idx);
Expand Down

0 comments on commit f8f2058

Please sign in to comment.