aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/graphics/windowed.h8
-rw-r--r--backends/platform/psp/cursor.cpp10
-rw-r--r--backends/platform/psp/input.cpp28
-rw-r--r--backends/platform/psp/input.h4
-rw-r--r--engines/cryo/eden.cpp2
-rw-r--r--engines/xeen/combat.cpp11
-rw-r--r--engines/xeen/combat.h15
-rw-r--r--engines/xeen/dialogs_party.cpp4
-rw-r--r--engines/xeen/events.cpp3
-rw-r--r--engines/xeen/events.h3
-rw-r--r--engines/xeen/files.cpp128
-rw-r--r--engines/xeen/files.h40
-rw-r--r--engines/xeen/interface.cpp5
-rw-r--r--engines/xeen/interface_scene.cpp6
-rw-r--r--engines/xeen/locations.cpp2
-rw-r--r--engines/xeen/resources.cpp2
-rw-r--r--engines/xeen/resources.h2
-rw-r--r--engines/xeen/saves.cpp70
-rw-r--r--engines/xeen/saves.h11
-rw-r--r--engines/xeen/scripts.cpp2
-rw-r--r--engines/xeen/sprites.cpp6
-rw-r--r--engines/xeen/sprites.h1
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_menu.cpp1
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;