aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/savegame.cpp55
-rw-r--r--engines/sci/engine/savegame.h2
-rw-r--r--engines/sci/graphics/video32.h5
-rw-r--r--engines/sci/video/robot_decoder.cpp17
-rw-r--r--engines/sci/video/robot_decoder.h46
5 files changed, 110 insertions, 15 deletions
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 2306fc6f0b..433878429e 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -53,6 +53,7 @@
#include "sci/graphics/frameout.h"
#include "sci/graphics/palette32.h"
#include "sci/graphics/remap32.h"
+#include "sci/graphics/video32.h"
#endif
namespace Sci {
@@ -390,6 +391,12 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false);
}
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ g_sci->_video32->beforeSaveLoadWithSerializer(s);
+ }
+#endif
+
_segMan->saveLoadWithSerializer(s);
g_sci->_soundCmd->syncPlayList(s);
@@ -399,6 +406,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
g_sci->_gfxPalette32->saveLoadWithSerializer(s);
g_sci->_gfxRemap32->saveLoadWithSerializer(s);
g_sci->_gfxCursor32->saveLoadWithSerializer(s);
+ g_sci->_video32->saveLoadWithSerializer(s);
} else
#endif
g_sci->_gfxPalette16->saveLoadWithSerializer(s);
@@ -972,6 +980,53 @@ void GfxCursor32::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
+
+void Video32::beforeSaveLoadWithSerializer(Common::Serializer &s) {
+ if (getSciVersion() < SCI_VERSION_3 || s.isSaving()) {
+ return;
+ }
+
+ _robotPlayer.close();
+}
+
+void Video32::saveLoadWithSerializer(Common::Serializer &s) {
+ if (getSciVersion() < SCI_VERSION_3) {
+ return;
+ }
+
+ bool robotExists = _robotPlayer.getStatus() != RobotDecoder::kRobotStatusUninitialized;
+ s.syncAsByte(robotExists);
+ if (robotExists) {
+ GuiResourceId robotId;
+ reg_t planeId;
+ Common::Point position;
+ int16 priority, scale;
+ int frameNo;
+
+ if (s.isSaving()) {
+ robotId = _robotPlayer.getResourceId();
+ planeId = _robotPlayer.getPlaneId();
+ priority = _robotPlayer.getPriority();
+ position = _robotPlayer.getPosition();
+ scale = _robotPlayer.getScale();
+ frameNo = _robotPlayer.getFrameNo();
+ }
+
+ s.syncAsUint16LE(robotId);
+ syncWithSerializer(s, planeId);
+ s.syncAsSint16LE(priority);
+ s.syncAsSint16LE(position.x);
+ s.syncAsSint16LE(position.y);
+ s.syncAsSint16LE(scale);
+ s.syncAsSint32LE(frameNo);
+
+ if (s.isLoading()) {
+ _robotPlayer.open(robotId, planeId, priority, position.x, position.y, scale);
+ _robotPlayer.showFrame(frameNo, position.x, position.y, priority);
+ }
+ }
+}
+
#endif
void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 53377f0b4d..6284897bd0 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,7 +37,7 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
- * 42 - initial SCI3 support
+ * 42 - SCI3 robots and VM objects
* 41 - palette support for newer SCI2.1 games; stable SCI2/2.1 save games
* 40 - always store palvary variables
* 39 - Accurate SCI32 arrays/strings, score metadata, avatar metadata
diff --git a/engines/sci/graphics/video32.h b/engines/sci/graphics/video32.h
index f8d6cbec56..3200105fc9 100644
--- a/engines/sci/graphics/video32.h
+++ b/engines/sci/graphics/video32.h
@@ -642,7 +642,7 @@ private:
* Video32 provides facilities for playing back
* video in SCI engine.
*/
-class Video32 {
+class Video32 : public Common::Serializable {
public:
Video32(SegManager *segMan, EventManager *eventMan) :
_SEQPlayer(segMan),
@@ -651,6 +651,9 @@ public:
_robotPlayer(segMan),
_duckPlayer(segMan, eventMan) {}
+ void beforeSaveLoadWithSerializer(Common::Serializer &ser);
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+
SEQPlayer &getSEQPlayer() { return _SEQPlayer; }
AVIPlayer &getAVIPlayer() { return _AVIPlayer; }
VMDPlayer &getVMDPlayer() { return _VMDPlayer; }
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index ba8a4683dd..6a4e912218 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -371,6 +371,8 @@ void RobotDecoder::initStream(const GuiResourceId robotId) {
error("Unable to open robot file %s", fileName.c_str());
}
+ _robotId = robotId;
+
const uint16 id = stream->readUint16LE();
if (id != 0x16) {
error("Invalid robot file %s", fileName.c_str());
@@ -437,17 +439,16 @@ void RobotDecoder::initAudio() {
void RobotDecoder::initVideo(const int16 x, const int16 y, const int16 scale, const reg_t plane, const bool hasPalette, const uint16 paletteSize) {
_position = Common::Point(x, y);
- if (scale != 128) {
- _scaleInfo.x = scale;
- _scaleInfo.y = scale;
- _scaleInfo.signal = kScaleSignalManual;
- }
+ _scaleInfo.x = scale;
+ _scaleInfo.y = scale;
+ _scaleInfo.signal = scale == 128 ? kScaleSignalNone : kScaleSignalManual;
_plane = g_sci->_gfxFrameout->getPlanes().findByObject(plane);
if (_plane == nullptr) {
error("Invalid plane %04x:%04x passed to RobotDecoder::open", PRINT_REG(plane));
}
+ _planeId = plane;
_minFrameRate = _frameRate - kMaxFrameRateDrift;
_maxFrameRate = _frameRate + kMaxFrameRateDrift;
@@ -585,6 +586,8 @@ void RobotDecoder::close() {
debugC(kDebugLevelVideo, "Closing robot");
+ _robotId = -1;
+ _planeId = NULL_REG;
_status = kRobotStatusUninitialized;
_videoSizes.clear();
_recordPositions.clear();
@@ -1343,6 +1346,10 @@ void RobotDecoder::expandCel(byte* target, const byte* source, const int16 celWi
}
}
+int16 RobotDecoder::getPriority() const {
+ return _priority;
+}
+
void RobotDecoder::setPriority(const int16 newPriority) {
_priority = newPriority;
}
diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h
index 9d8c720968..aa1d9da75c 100644
--- a/engines/sci/video/robot_decoder.h
+++ b/engines/sci/video/robot_decoder.h
@@ -469,23 +469,25 @@ public:
#pragma mark RobotDecoder
/**
- * RobotDecoder implements the logic required
- * for Robot animations.
- *
- * @note A paused or finished RobotDecoder was
- * classified as serializable in SCI3, but the
- * save/load code would attempt to use uninitialised
- * values, so it seems that robots were not ever
- * actually able to be saved.
+ * RobotDecoder implements the logic required for Robot animations.
*/
class RobotDecoder {
public:
RobotDecoder(SegManager *segMan);
~RobotDecoder();
+ GuiResourceId getResourceId() const {
+ return _robotId;
+ }
+
private:
SegManager *_segMan;
+ /**
+ * The ID of the currently loaded robot.
+ */
+ GuiResourceId _robotId;
+
#pragma mark Constants
public:
/**
@@ -1175,6 +1177,27 @@ private:
#pragma mark Rendering
public:
/**
+ * Gets the plane used to render the robot.
+ */
+ const reg_t getPlaneId() const {
+ return _planeId;
+ }
+
+ /**
+ * Gets the origin of the robot.
+ */
+ Common::Point getPosition() const {
+ return _position;
+ }
+
+ /**
+ * Gets the scale of the robot.
+ */
+ int16 getScale() const {
+ return _scaleInfo.x;
+ }
+
+ /**
* Puts the current dimensions of the robot, in game script
* coordinates, into the given rect, and returns the total
* number of frames in the robot animation.
@@ -1207,6 +1230,8 @@ public:
*/
void expandCel(byte *target, const byte* source, const int16 celWidth, const int16 celHeight) const;
+ int16 getPriority() const;
+
/**
* Sets the visual priority of the robot.
* @see Plane::_priority
@@ -1292,6 +1317,11 @@ private:
DecompressorLZS _decompressor;
/**
+ * The ID of the robot plane.
+ */
+ reg_t _planeId;
+
+ /**
* The origin of the robot animation, in screen
* coordinates.
*/