diff options
Diffstat (limited to 'engines/xeen')
-rw-r--r-- | engines/xeen/files.cpp | 12 | ||||
-rw-r--r-- | engines/xeen/files.h | 16 | ||||
-rw-r--r-- | engines/xeen/map.cpp | 156 | ||||
-rw-r--r-- | engines/xeen/map.h | 31 |
4 files changed, 161 insertions, 54 deletions
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index d63c63d651..a889cfb95e 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -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); } diff --git a/engines/xeen/files.h b/engines/xeen/files.h index f18d23671a..34a96906cf 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -274,18 +274,32 @@ public: 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; }; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 369202bedc..cf7ef8245c 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -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) { @@ -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); } /*------------------------------------------------------------------------*/ @@ -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() { @@ -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)); } @@ -958,6 +964,7 @@ void Map::load(int mapId) { intf._objNumber = 0; party._stepped = true; party._mazeId = mapId; + saveMaze(); events.clearEvents(); _sideObjects = 1; @@ -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) @@ -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) { diff --git a/engines/xeen/map.h b/engines/xeen/map.h index c74f084392..6734f3f16c 100644 --- a/engines/xeen/map.h +++ b/engines/xeen/map.h @@ -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" @@ -114,7 +115,7 @@ public: void clear(); - void synchronize(Common::SeekableReadStream &s); + void synchronize(XeenSerializer &s); int &operator[](int idx); }; @@ -132,7 +133,10 @@ public: public: MazeDifficulties(); - void synchronize(Common::SeekableReadStream &s); + /** + * Synchronizes data for the item + */ + void synchronize(XeenSerializer &s); }; enum MazeFlags { @@ -208,7 +212,10 @@ public: 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 @@ -395,6 +402,21 @@ private: * 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; @@ -433,6 +455,9 @@ public: 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); |