diff options
-rw-r--r-- | backends/graphics/windowed.h | 8 | ||||
-rw-r--r-- | backends/platform/psp/cursor.cpp | 10 | ||||
-rw-r--r-- | backends/platform/psp/input.cpp | 28 | ||||
-rw-r--r-- | backends/platform/psp/input.h | 4 | ||||
-rw-r--r-- | engines/cryo/eden.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/combat.cpp | 11 | ||||
-rw-r--r-- | engines/xeen/combat.h | 15 | ||||
-rw-r--r-- | engines/xeen/dialogs_party.cpp | 4 | ||||
-rw-r--r-- | engines/xeen/events.cpp | 3 | ||||
-rw-r--r-- | engines/xeen/events.h | 3 | ||||
-rw-r--r-- | engines/xeen/files.cpp | 128 | ||||
-rw-r--r-- | engines/xeen/files.h | 40 | ||||
-rw-r--r-- | engines/xeen/interface.cpp | 5 | ||||
-rw-r--r-- | engines/xeen/interface_scene.cpp | 6 | ||||
-rw-r--r-- | engines/xeen/locations.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/resources.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/resources.h | 2 | ||||
-rw-r--r-- | engines/xeen/saves.cpp | 70 | ||||
-rw-r--r-- | engines/xeen/saves.h | 11 | ||||
-rw-r--r-- | engines/xeen/scripts.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/sprites.cpp | 6 | ||||
-rw-r--r-- | engines/xeen/sprites.h | 1 | ||||
-rw-r--r-- | engines/xeen/worldofxeen/worldofxeen_menu.cpp | 1 |
23 files changed, 253 insertions, 111 deletions
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h index 1d4958c9d6..5f89d2d233 100644 --- a/backends/graphics/windowed.h +++ b/backends/graphics/windowed.h @@ -94,8 +94,8 @@ protected: error("convertVirtualToWindow called without a valid draw rect"); } - return Common::Point(targetX + x * targetWidth / sourceWidth, - targetY + y * targetHeight / sourceHeight); + return Common::Point(targetX + (x * targetWidth + sourceWidth / 2) / sourceWidth, + targetY + (y * targetHeight + sourceHeight / 2) / sourceHeight); } /** @@ -120,8 +120,8 @@ protected: x = CLIP<int>(x, sourceX, sourceMaxX); y = CLIP<int>(y, sourceY, sourceMaxY); - return Common::Point(((x - sourceX) * targetWidth) / sourceWidth, - ((y - sourceY) * targetHeight) / sourceHeight); + return Common::Point(((x - sourceX) * targetWidth + sourceWidth / 2) / sourceWidth, + ((y - sourceY) * targetHeight + sourceHeight / 2) / sourceHeight); } /** diff --git a/backends/platform/psp/cursor.cpp b/backends/platform/psp/cursor.cpp index 376e7eb3e5..b7c69d5b98 100644 --- a/backends/platform/psp/cursor.cpp +++ b/backends/platform/psp/cursor.cpp @@ -204,15 +204,15 @@ void Cursor::setLimits(uint32 width, uint32 height) { inline void Cursor::adjustXYForScreenSize(int32 &x, int32 &y) { DEBUG_ENTER_FUNC(); // We have our speed calibrated for the y axis at 480x272. The idea is to adjust this for other - // resolutions and for x, which is wider. + // resolutions int32 newX = x, newY = y; if (_mouseLimitWidth >= 600) { // multiply by 2 - newX <<= 1; - newY <<= 1; + newX *= 2; + newY *= 2; } else if (_mouseLimitWidth >= 480) { // multiply by 1.5 - newX = newX + (newX >> 1); - newY = newY + (newY >> 1); + newX = newX + (newX / 2); + newY = newY + (newY / 2); } } diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp index b5d90803d6..7a2047f28e 100644 --- a/backends/platform/psp/input.cpp +++ b/backends/platform/psp/input.cpp @@ -37,7 +37,7 @@ #define PSP_TRIGGERS (PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER) #define PSP_ALL_BUTTONS (PSP_DPAD | PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START | PSP_CTRL_SELECT) -#define PAD_CHECK_TIME 14 // was 53 +#define PAD_CHECK_TIME 13 // was 53 Button::Button() { clear(); @@ -280,12 +280,6 @@ bool Nub::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { analogStepX = modifyNubAxisMotion(analogStepX); analogStepY = modifyNubAxisMotion(analogStepY); - static int32 hiresX = 0; - static int32 hiresY = 0; - - hiresX += analogStepX; - hiresY += analogStepY; - int32 speedFactor = 25; switch (ConfMan.getInt("kbdmouse_speed")) { // 0.25 keyboard pointer speed @@ -324,18 +318,24 @@ bool Nub::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { speedFactor = 25; } - int32 additionalFactor = 32; + // the larger the factor, the slower the cursor will move + int32 additionalFactor = 16; if (_shifted) { - additionalFactor = 256; + additionalFactor = 192; } - int32 factor = speedFactor * additionalFactor / 25; + int32 factor = (speedFactor * additionalFactor) / 25; + + // hi-res cumulative analog delta for sub-pixel cursor positioning + _hiresX += (analogStepX * 1024) / factor; + _hiresY += (analogStepY * 1024) / factor; - analogStepX = hiresX / factor; - analogStepY = hiresY / factor; + analogStepX = (_hiresX / 1024); + analogStepY = (_hiresY / 1024); - hiresX %= factor; - hiresY %= factor; + // keep track of remainder for true sub-pixel cursor position + _hiresX %= 1024; + _hiresY %= 1024; int32 oldX = _cursor->getX(); int32 oldY = _cursor->getY(); diff --git a/backends/platform/psp/input.h b/backends/platform/psp/input.h index 05b575e0b0..ff89b9faec 100644 --- a/backends/platform/psp/input.h +++ b/backends/platform/psp/input.h @@ -139,6 +139,8 @@ private: Cursor *_cursor; // to enable changing/getting cursor position ShiftMode _shifted; + int32 _hiresX; // to accumulate analog X over many frames + int32 _hiresY; // to accumulate analog Y over many frames bool _dpadMode; ButtonPad _buttonPad; // private buttonpad for dpad mode @@ -146,7 +148,7 @@ private: int32 modifyNubAxisMotion(int32 input); void translateToDpadState(int dpadX, int dpadY, uint32 &buttonState); // convert nub data to dpad data public: - Nub() : _shifted(UNSHIFTED), _dpadMode(false) { } + Nub() : _shifted(UNSHIFTED), _dpadMode(false), _hiresX(0), _hiresY(0) { } void init() { _buttonPad.initButtons(); } void setCursor(Cursor *cursor) { _cursor = cursor; } diff --git a/engines/cryo/eden.cpp b/engines/cryo/eden.cpp index 78dd622302..103d9fde9e 100644 --- a/engines/cryo/eden.cpp +++ b/engines/cryo/eden.cpp @@ -3126,13 +3126,11 @@ void EdenGame::tyranDies(perso_t *perso) { } void EdenGame::specialObjects(perso_t *perso, char objid) { -#pragma pack(push, 1) struct SpecialObject { int8 _characterType; int8 _objectId; void (EdenGame::*dispFct)(perso_t *perso); }; -#pragma pack(pop) static SpecialObject kSpecialObjectActions[] = { // persoType, objectId, dispFct diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index fe2eaa94bf..6a0aa20169 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -127,10 +127,14 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _rangeType = RT_SINGLE; } -void Combat::clear() { +void Combat::clearAttackers() { Common::fill(&_attackMonsters[0], &_attackMonsters[ATTACK_MONSTERS_COUNT], -1); } +void Combat::clearBlocked() { + Common::fill(_charsBlocked, _charsBlocked + PARTY_AND_MONSTERS, false); +} + void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) { Party &party = *_vm->_party; Scripts &scripts = *_vm->_scripts; @@ -645,7 +649,7 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) { Party &party = *_vm->_party; for (int idx = 0; idx < 36; ++idx) { - if (_gmonHit[idx] != -1) { + if (_gmonHit[idx] == -1) { int result = stopAttack(pt - party._mazePosition); if (result) { _monstersAttacking = true; @@ -773,7 +777,7 @@ void Combat::doMonsterTurn(int monsterId) { Party &party = *_vm->_party; Sound &sound = *_vm->_sound; - if (_monstersAttacking) { + if (!_monstersAttacking) { int monsterIndex; switch (_whosTurn - _combatParty.size()) { case 0: @@ -790,6 +794,7 @@ void Combat::doMonsterTurn(int monsterId) { intf._indoorList[153]._scale = 0; } + assert(monsterIndex != -1); MazeMonster &monster = map._mobData._monsters[monsterIndex]; MonsterStruct &monsterData = *monster._monsterData; if (monster._damageType) diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index f3eaa39bd0..fc7f9ed0dc 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -104,7 +104,7 @@ private: void giveExperience(int experience); public: Common::Array<Character *> _combatParty; - Common::Array<bool> _charsBlocked; + bool _charsBlocked[PARTY_AND_MONSTERS]; Common::Array<int> _charsGone; SpriteResource _powSprites; int _attackMonsters[ATTACK_MONSTERS_COUNT]; @@ -145,7 +145,15 @@ public: public: Combat(XeenEngine *vm); - void clear(); + /** + * Clear the list of attacking monsters + */ + void clearAttackers(); + + /** + * Clear the list of blocked characters + */ + void clearBlocked(); void giveCharDamage(int damage, DamageType attackType, int charIndex); @@ -195,6 +203,9 @@ public: */ void run(); + /** + * Called to handle monsters doing ranged attacks against the party + */ void monstersAttack(); void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp index f4d95ca612..64f57d62e8 100644 --- a/engines/xeen/dialogs_party.cpp +++ b/engines/xeen/dialogs_party.cpp @@ -133,7 +133,7 @@ void PartyDialog::execute() { party._mazeId = party._priorMazeId; party.copyPartyToRoster(); - _vm->_saves->writeCharFile(); + //_vm->_saves->writeCharFile(); return; } break; @@ -208,7 +208,7 @@ void PartyDialog::execute() { createChar(); party.copyPartyToRoster(); - _vm->_saves->writeCharFile(); + //_vm->_saves->writeCharFile(); screen.fadeOut(); modeFlag = true; breakFlag = true; diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp index cc58edda89..babfdcb397 100644 --- a/engines/xeen/events.cpp +++ b/engines/xeen/events.cpp @@ -31,7 +31,7 @@ namespace Xeen { -EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), +EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _playTime(0), _frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0), _leftButton(false), _rightButton(false), _sprites("mouse.icn") { Common::fill(&_gameCounters[0], &_gameCounters[6], 0); @@ -181,6 +181,7 @@ void EventsManager::waitForPressAnimated() { void EventsManager::nextFrame() { ++_frameCounter; + ++_playTime; // Allow debugger to update _vm->_debugger->update(); diff --git a/engines/xeen/events.h b/engines/xeen/events.h index cf74a641c6..e6018f6a87 100644 --- a/engines/xeen/events.h +++ b/engines/xeen/events.h @@ -41,6 +41,7 @@ private: uint32 _priorFrameCounterTime; uint32 _gameCounter; uint32 _gameCounters[6]; + uint32 _playTime; Common::Queue<Common::KeyState> _keys; SpriteResource _sprites; @@ -107,6 +108,8 @@ public: uint32 timeElapsed4() const { return _frameCounter - _gameCounters[4]; } uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; } uint32 getTicks() { return _frameCounter; } + uint32 playTime() const { return _playTime; } + void setPlayTime(uint32 time) { _playTime = time; } bool wait(uint numFrames, bool interruptable = true); diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index 375b9df65a..912c9533d8 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -23,6 +23,7 @@ #include "common/scummsys.h" #include "common/archive.h" #include "common/memstream.h" +#include "common/substream.h" #include "common/textconsole.h" #include "xeen/xeen.h" #include "xeen/files.h" @@ -55,18 +56,17 @@ uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) { return total; } -void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) { - int count = stream->readUint16LE(); +void BaseCCArchive::loadIndex(Common::SeekableReadStream &stream) { + int count = stream.readUint16LE(); // Read in the data for the archive's index byte *rawIndex = new byte[count * 8]; - stream->read(rawIndex, count * 8); + stream.read(rawIndex, count * 8); // Decrypt the index - int ah = 0xac; - for (int i = 0; i < count * 8; ++i) { - rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + ah) & 0xff); - ah += 0x67; + int seed = 0xac; + for (int i = 0; i < count * 8; ++i, seed += 0x67) { + rawIndex[i] = (byte)(((rawIndex[i] << 2 | rawIndex[i] >> 6) + seed) & 0xff); } // Extract the index data into entry structures @@ -85,14 +85,51 @@ void BaseCCArchive::loadIndex(Common::SeekableReadStream *stream) { delete[] rawIndex; } +void BaseCCArchive::saveIndex(Common::WriteStream &stream) { + // First caclculate file offsets for each resource, since replaced resources + // will shift file offsets for even the succeeding unchanged resources + for (uint idx = 1, pos = _index[0]._offset + _index[0]._size; idx < _index.size(); ++idx) { + _index[idx]._offset = pos; + pos += _index[idx]._size; + } + + // Fill up the data for the index entries into a raw data block + byte data[8]; + byte *rawIndex = new byte[_index.size() * 8]; + + byte *entryP = rawIndex; + for (uint i = 0; i < _index.size(); ++i, entryP += 8) { + CCEntry &entry = _index[i]; + WRITE_LE_UINT16(&entryP[0], entry._id); + WRITE_LE_UINT32(&entryP[2], entry._offset); + WRITE_LE_UINT16(&entryP[5], entry._size); + entryP[7] = 0; + } + + // Encrypt the index + int seed = 0xac; + for (uint i = 0; i < _index.size() * 8; ++i, seed += 0x67) { + byte b = (seed - rawIndex[i]) && 0xff; + rawIndex[i] = ((b >> 2) & 0x3f) | ((b & 3) << 6); + } + + // Write out the number of entries and the encrypted index data + stream.writeUint16LE(_index.size()); + stream.write(rawIndex, _index.size() * 8); + + delete[] rawIndex; +} + bool BaseCCArchive::hasFile(const Common::String &name) const { CCEntry ccEntry; return getHeaderEntry(name, ccEntry); } bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const { - uint16 id = convertNameToId(resourceName); + return getHeaderEntry(convertNameToId(resourceName), ccEntry); +} +bool BaseCCArchive::getHeaderEntry(uint16 id, CCEntry &ccEntry) const { // Loop through the index for (uint i = 0; i < _index.size(); ++i) { if (_index[i]._id == id) { @@ -122,7 +159,7 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const { CCArchive::CCArchive(const Common::String &filename, bool encoded): BaseCCArchive(), _filename(filename), _encoded(encoded) { File f(filename, SearchMan); - loadIndex(&f); + loadIndex(f); } CCArchive::CCArchive(const Common::String &filename, const Common::String &prefix, @@ -130,7 +167,7 @@ CCArchive::CCArchive(const Common::String &filename, const Common::String &prefi _prefix(prefix), _encoded(encoded) { _prefix.toLowercase(); File f(filename, SearchMan); - loadIndex(&f); + loadIndex(f); } CCArchive::~CCArchive() { @@ -370,18 +407,22 @@ SaveArchive::~SaveArchive() { } Common::SeekableReadStream *SaveArchive::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); + return createReadStreamForMember(id); +} + +Common::SeekableReadStream *SaveArchive::createReadStreamForMember(uint16 id) const { 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)) { + CCEntry ccEntry; + if (getHeaderEntry(id, ccEntry)) { // Open the correct CC entry return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size); } @@ -389,13 +430,14 @@ Common::SeekableReadStream *SaveArchive::createReadStreamForMember(const Common: return nullptr; } -void SaveArchive::load(Common::SeekableReadStream *stream) { +void SaveArchive::load(Common::SeekableReadStream &stream) { loadIndex(stream); delete[] _data; - _data = new byte[stream->size()]; - stream->seek(0); - stream->read(_data, stream->size()); + _dataSize = stream.size(); + _data = new byte[_dataSize]; + stream.seek(0); + stream.read(_data, _dataSize); // Load in the character stats and active party Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr"); @@ -432,7 +474,53 @@ void SaveArchive::reset(CCArchive *src) { assert(saveFile.size() > 0); Common::MemoryReadStream f(saveFile.getData(), saveFile.size()); - load(&f); + load(f); +} + +void SaveArchive::save(Common::WriteStream &s) { + // Save the character stats and active party + OutFile chr("maze.chr", this); + XeenSerializer sChr(nullptr, &chr); + _party->_roster.synchronize(sChr); + + OutFile pty("maze.pty", this); + Common::Serializer sPty(nullptr, &pty); + _party->synchronize(sPty); + + // Save out the index + saveIndex(s); + + // Save out each resource in turn + for (uint idx = 0; idx < _index.size(); ++idx) { + // Get the entry + Common::SeekableReadStream *entry = createReadStreamForMember(_index[idx]._id); + byte *data = new byte[entry->size()]; + entry->read(data, entry->size()); + + // Write it out to the savegame + s.write(data, entry->size()); + delete[] data; + delete entry; + } +} + +void SaveArchive::replaceEntry(uint16 id, const byte *data, size_t size) { + // Delete any prior set entry + if (_newData.contains(id)) + delete _newData[id]; + + // Create a new entry and write out the data to it + Common::MemoryWriteStreamDynamic *out = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); + out->write(data, size); + _newData[id] = out; + + // Update the index with the entry's size for later convenience when creating savegames + for (uint idx = 0; idx < _index.size(); ++idx) { + if (_index[idx]._id == id) { + _index[idx]._size = size; + break; + } + } } /*------------------------------------------------------------------------*/ @@ -463,11 +551,7 @@ int32 OutFile::pos() const { void OutFile::finalize() { uint16 id = BaseCCArchive::convertNameToId(_filename); - if (!_archive->_newData.contains(id)) - _archive->_newData[id] = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); - - Common::MemoryWriteStreamDynamic *out = _archive->_newData[id]; - out->write(_backingStream.getData(), _backingStream.size()); + _archive->replaceEntry(id, _backingStream.getData(), _backingStream.size()); } } // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h index 34a96906cf..b528658566 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -213,13 +213,24 @@ protected: /** * Load the index of a given CC file */ - void loadIndex(Common::SeekableReadStream *stream); + void loadIndex(Common::SeekableReadStream &stream); + + /** + * Saves out the contents of the index. Used when creating savegames + */ + void saveIndex(Common::WriteStream &stream); /** * Given a resource name, returns whether an entry exists, and returns * the header index data for that entry */ virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const; + + /** + * Given a resource Id, returns whether an entry exists, and returns + * the header index data for that entry + */ + virtual bool getHeaderEntry(uint16 id, CCEntry &ccEntry) const; public: /** * Hash a given filename to produce the Id that represents it @@ -258,9 +269,8 @@ class SaveArchive : public BaseCCArchive { private: Party *_party; byte *_data; + uint32 _dataSize; Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *> _newData; - - void load(Common::SeekableReadStream *stream); public: SaveArchive(Party *party); ~SaveArchive(); @@ -270,8 +280,30 @@ public: */ void reset(CCArchive *src); - // Archive implementation + /** + * Archive implementation + */ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; + + /** + * Archive implementation + */ + virtual Common::SeekableReadStream *createReadStreamForMember(uint16 id) const; + + /** + * Loads a save archive from a stream + */ + void load(Common::SeekableReadStream &stream); + + /** + * Saves a save archive to a savegame + */ + void save(Common::WriteStream &s); + + /** + * Sets a new resource entry + */ + void replaceEntry(uint16 id, const byte *data, size_t size); }; /** diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index 0cc509a66a..b9f1e2bb2c 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -1497,7 +1497,7 @@ void Interface::doCombat() { combat._combatParty.clear(); combat._charsGone.clear(); - combat._charsBlocked.clear(); + combat.clearBlocked(); combat._charsArray1[0] = 0; combat._charsArray1[1] = 0; combat._charsArray1[2] = 0; @@ -1510,7 +1510,6 @@ void Interface::doCombat() { // Initialize arrays for character/monster states combat._charsGone.resize(combat._speedTable.size()); - combat._charsBlocked.resize(combat._speedTable.size()); Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._speedTable.size(), 0); Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[0] + combat._speedTable.size(), false); @@ -1691,7 +1690,7 @@ void Interface::doCombat() { // Handling for if the combat turn is complete if (combat.allHaveGone()) { Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._charsGone.size(), false); - Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[0] + combat._charsBlocked.size(), false); + combat.clearBlocked(); combat.setSpeedTable(); combat._whosTurn = -1; combat._whosSpeed = -1; diff --git a/engines/xeen/interface_scene.cpp b/engines/xeen/interface_scene.cpp index 710b34d94b..4aa37562fb 100644 --- a/engines/xeen/interface_scene.cpp +++ b/engines/xeen/interface_scene.cpp @@ -433,7 +433,7 @@ void InterfaceScene::drawOutdoorsScene() { Map &map = *_vm->_map; for (int idx = 0; idx < 44; ++idx) - _outdoorList[Res.OUTDOOR_DRAWSTRCT_INDEXES[idx]]._frame = -1; + _outdoorList[Res.OUTDOOR_DRAWSTRUCT_INDEXES[idx]]._frame = -1; if (combat._monstersAttacking) { for (int idx = 0; idx < 8; ++idx) { @@ -2316,7 +2316,7 @@ void InterfaceScene::setIndoorsMonsters() { Direction dir = _vm->_party->_mazeDirection; // Reset the list of attacking monsters - combat.clear(); + combat.clearAttackers(); // Iterate through the monsters list checking for proximity to party for (uint monsterIdx = 0; monsterIdx < map._mobData._monsters.size(); ++monsterIdx) { @@ -3101,7 +3101,7 @@ void InterfaceScene::setOutdoorsMonsters() { Common::Point pt = party._mazePosition; // Reset the list of attacking monsters - combat.clear(); + combat.clearAttackers(); // Iterate through the monsters list checking for proximity to party for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) { diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp index 11391736d5..647eebac71 100644 --- a/engines/xeen/locations.cpp +++ b/engines/xeen/locations.cpp @@ -104,7 +104,7 @@ int BaseLocation::show() { party.addTime(_farewellTime); result = 0; } else { - _vm->_saves->saveChars(); + //_vm->_saves->saveChars(); result = 2; } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index f9b6548404..0ef55dc33a 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -721,7 +721,7 @@ const int Resources::MAKE_ITEM_ARR5[8][2] = { { 51, 60 }, { 61, 73 }, { 61, 73 } }; -const int Resources::OUTDOOR_DRAWSTRCT_INDEXES[44] = { +const int Resources::OUTDOOR_DRAWSTRUCT_INDEXES[44] = { 37, 38, 39, 40, 41, 44, 42, 43, 47, 45, 46, 48, 49, 52, 50, 51, 66, 67, 68, 69, 70, 71, 72, 75, 73, 74, 87, 88, 89, 90, 91, 94, 92, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 61581594e8..9bde8da691 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -122,7 +122,7 @@ public: static const int MAKE_ITEM_ARR3[10][7][2]; static const int MAKE_ITEM_ARR4[2][7][2]; static const int MAKE_ITEM_ARR5[8][2]; - static const int OUTDOOR_DRAWSTRCT_INDEXES[44]; + static const int OUTDOOR_DRAWSTRUCT_INDEXES[44]; static const int TOWN_MAXES[2][11]; static const char *const TOWN_ACTION_MUSIC[2][7]; static const char *const TOWN_ACTION_SHAPES[7]; diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp index 504bb18dd7..2a6b7d6619 100644 --- a/engines/xeen/saves.cpp +++ b/engines/xeen/saves.cpp @@ -23,6 +23,7 @@ #include "common/scummsys.h" #include "common/algorithm.h" #include "common/memstream.h" +#include "common/substream.h" #include "graphics/scaler.h" #include "graphics/thumbnail.h" #include "xeen/saves.h" @@ -61,18 +62,6 @@ SavesManager::~SavesManager() { delete File::_darkSave; } -void SavesManager::readCharFile() { - warning("TODO: readCharFile"); -} - -void SavesManager::writeCharFile() { - warning("TODO: writeCharFile"); -} - -void SavesManager::saveChars() { - warning("TODO: saveChars"); -} - const char *const SAVEGAME_STR = "XEEN"; #define SAVEGAME_STR_SIZE 6 @@ -112,6 +101,9 @@ bool SavesManager::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader } void SavesManager::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHeader &header) { + EventsManager &events = *g_vm->_events; + Screen &screen = *g_vm->_screen; + // Write out a savegame header out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); @@ -122,15 +114,14 @@ void SavesManager::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHea out->writeByte('\0'); // Write a thumbnail of the screen - /* uint8 thumbPalette[768]; - _screen->getPalette(thumbPalette); + screen.getPalette(thumbPalette); Graphics::Surface saveThumb; - ::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(), - _screen->w, _screen->h, thumbPalette); + ::createThumbnail(&saveThumb, (const byte *)screen.getPixels(), + screen.w, screen.h, thumbPalette); Graphics::saveThumbnail(*out, saveThumb); saveThumb.free(); - */ + // Write out the save date/time TimeDate td; g_system->getTimeAndDate(td); @@ -139,7 +130,7 @@ void SavesManager::writeSavegameHeader(Common::OutSaveFile *out, XeenSavegameHea out->writeSint16LE(td.tm_mday); out->writeSint16LE(td.tm_hour); out->writeSint16LE(td.tm_min); - // out->writeUint32LE(_events->getFrameCounter()); + out->writeUint32LE(events.playTime()); } Common::Error SavesManager::saveGameState(int slot, const Common::String &desc) { @@ -148,12 +139,25 @@ Common::Error SavesManager::saveGameState(int slot, const Common::String &desc) if (!out) return Common::kCreatingFileFailed; + // Push map and party data to the save archives + Map &map = *g_vm->_map; + map.saveMaze(); + + XeenSavegameHeader header; header._saveName = desc; writeSavegameHeader(out, header); - Common::Serializer s(nullptr, out); - synchronize(s); + // Loop through saving the sides' save archives + SaveArchive *archives[2] = { File::_xeenSave, File::_darkSave }; + for (int idx = 0; idx < 2; ++idx) { + if (archives[idx]) { + archives[idx]->save(*out); + } else { + // Side isn't present + out->writeUint32LE(0); + } + } out->finalize(); delete out; @@ -167,8 +171,6 @@ Common::Error SavesManager::loadGameState(int slot) { if (!saveFile) return Common::kReadingFailed; - Common::Serializer s(saveFile, nullptr); - // Load the savaegame header XeenSavegameHeader header; if (!readSavegameHeader(saveFile, header)) @@ -179,9 +181,22 @@ Common::Error SavesManager::loadGameState(int slot) { delete header._thumbnail; } - // Load most of the savegame data - synchronize(s); - delete saveFile; + // Set the total play time + g_vm->_events->setPlayTime(header._totalFrames); + + // Loop through loading the sides' save archives + SaveArchive *archives[2] = { File::_xeenSave, File::_darkSave }; + for (int idx = 0; idx < 2; ++idx) { + uint fileSize = saveFile->readUint32LE(); + + if (archives[idx]) { + Common::SeekableSubReadStream arcStream(saveFile, saveFile->pos(), + saveFile->pos() + fileSize); + archives[idx]->load(arcStream); + } else { + assert(!fileSize); + } + } return Common::kNoError; } @@ -190,9 +205,4 @@ Common::String SavesManager::generateSaveName(int slot) { return Common::String::format("%s.%03d", _targetName.c_str(), slot); } -void SavesManager::synchronize(Common::Serializer &s) { - // TODO -} - - } // End of namespace Xeen diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h index 2711cc7f2c..c236bee0fe 100644 --- a/engines/xeen/saves.h +++ b/engines/xeen/saves.h @@ -46,11 +46,6 @@ private: Common::String _targetName; private: /** - * Synchronize savegame data - */ - void synchronize(Common::Serializer &s); - - /** * Support method that generates a savegame name * @param slot Slot number */ @@ -67,12 +62,6 @@ public: SavesManager(const Common::String &targetName); ~SavesManager(); - void readCharFile(); - - void writeCharFile(); - - void saveChars(); - /** * Read in a savegame header */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 99603224c8..46485a543b 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1425,7 +1425,7 @@ void Scripts::doWorldEnding() { } void Scripts::doEnding(const Common::String &endStr) { - _vm->_saves->saveChars(); + //_vm->_saves->saveChars(); Party &party = *_vm->_party; diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 8ea18f0e10..fd699f6927 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -45,6 +45,12 @@ SpriteResource::SpriteResource(const Common::String &filename) { load(filename); } +SpriteResource::SpriteResource(const Common::String &filename, int ccMode) { + _data = nullptr; + _scaledWidth = _scaledHeight = 0; + load(filename, ccMode); +} + SpriteResource::~SpriteResource() { clear(); } diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 342fa3f39a..4c4a230b2e 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -85,6 +85,7 @@ private: public: SpriteResource(); SpriteResource(const Common::String &filename); + SpriteResource(const Common::String &filename, int ccMode); virtual ~SpriteResource(); diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp index b58bf64dc0..5b08c1adec 100644 --- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp +++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp @@ -51,6 +51,7 @@ void WorldOfXeenMenu::show(XeenEngine *vm) { } void WorldOfXeenMenu::execute() { + _vm->_files->setGameCc(1); SpriteResource special("special.icn"); Windows &windows = *_vm->_windows; EventsManager &events = *_vm->_events; |