[Scummvm-git-logs] scummvm master -> 82d41b17cdeaacca045ce57665976ec89de09489

fracturehill noreply at scummvm.org
Thu Apr 13 18:24:13 UTC 2023


This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
d2d65ffb28 NANCY: Make arfactory.cpp more readable
203d4fa5dc NANCY: Implement Overlay action record
e76e3c3f1f NANCY: Correctly load INV chunk in nancy2
9b1c62e489 NANCY: Add stub for SpecialEffect action record
2888248e7e NANCY: Add workaround for broken Overlay
50a08027ab NANCY: Implement ClosedCaptioning dependency
0befb73ecb NANCY: Implement TextBoxWrite action record
4e734c4778 NANCY: Correct viewport panning
82d41b17cd NANCY: Show virtual keyboard during password puzzle


Commit: d2d65ffb2831d78ad9d69c9f369a5180bef7b2bf
    https://github.com/scummvm/scummvm/commit/d2d65ffb2831d78ad9d69c9f369a5180bef7b2bf
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:35+03:00

Commit Message:
NANCY: Make arfactory.cpp more readable

Replaced the hexadecimal ActionRecord typeIDs and replaced
them with the ones found inside gameflow.h. Also updated
the scan_ar_type console command to match.

Changed paths:
    engines/nancy/action/arfactory.cpp
    engines/nancy/console.cpp


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index d99e77c5578..a49bae4a118 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -37,102 +37,101 @@ namespace Nancy {
 namespace Action {
 
 ActionRecord *ActionManager::createActionRecord(uint16 type) {
-	type -= 0xA;
 	switch (type) {
-	case 0x00:
+	case 10:
 		return new Hot1FrSceneChange();
-	case 0x01:
+	case 11:
 		return new HotMultiframeSceneChange();
-	case 0x02:
+	case 12:
 		return new SceneChange();
-	case 0x03:
+	case 13:
 		return new HotMultiframeMultisceneChange();
-	case 0x04:
+	case 14:
 		return new Hot1FrExitSceneChange();
-	case 0x0A:
+	case 20:
 		return new PaletteThisScene();
-	case 0x0B:
+	case 21:
 		return new PaletteNextScene();
-	case 0x1E:
+	case 40:
 		return new LightningOn();
-	case 0x28:
+	case 50:
 		return new PlayPrimaryVideoChan0();
-	case 0x29:
+	case 51:
 		return new PlaySecondaryVideo(0);
-	case 0x2A:
+	case 52:
 		return new PlaySecondaryVideo(1);
-	case 0x2B:
+	case 53:
 		return new PlaySecondaryMovie();
-	case 0x2C:
+	case 54:
 		return new PlayStaticBitmapAnimation(false); // PlayStaticBitmapAnimation
-	case 0x2D:
+	case 55:
 		return new PlayStaticBitmapAnimation(true); // PlayIntStaticBitmapAnimation
-	case 0x32:
+	case 60:
 		return new MapCall();
-	case 0x33:
+	case 61:
 		return new MapCallHot1Fr();
-	case 0x34:
+	case 62:
 		return new MapCallHotMultiframe();
-	case 0x41:
+	case 75:
 		return new TextBoxWrite();
-	case 0x42:
+	case 76:
 		return new TextBoxClear();
-	case 0x5A:
+	case 100:
 		return new BumpPlayerClock();
-	case 0x5B:
+	case 101:
 		return new SaveContinueGame();
-	case 0x5C:
+	case 102:
 		return new TurnOffMainRendering();
-	case 0x5D:
+	case 103:
 		return new TurnOnMainRendering();
-	case 0x5E:
+	case 104:
 		return new ResetAndStartTimer();
-	case 0x5F:
+	case 105:
 		return new StopTimer();
-	case 0x60:
+	case 106:
 		return new EventFlagsMultiHS();
-	case 0x61:
+	case 107:
 		return new EventFlags();
-	case 0x62:
+	case 108:
 		return new OrderingPuzzle();
-	case 0x63:
+	case 109:
 		return new LoseGame();
-	case 0x64:
+	case 110:
 		return new PushScene();
-	case 0x65:
+	case 111:
 		return new PopScene();
-	case 0x66:
+	case 112:
 		return new WinGame();
-	case 0x67:
+	case 113:
 		return new DifficultyLevel();
-	case 0x68:
+	case 114:
 		return new RotatingLockPuzzle();
-	case 0x69:
+	case 115:
 		return new LeverPuzzle();
-	case 0x6A:
+	case 116:
 		return new Telephone();
-	case 0x6B:
+	case 117:
 		return new SliderPuzzle();
-	case 0x6C:
+	case 118:
 		return new PasswordPuzzle();
-	case 0x6E:
+	case 120:
 		return new AddInventoryNoHS();
-	case 0x6F:
+	case 121:
 		return new RemoveInventoryNoHS();
-	case 0x70:
+	case 122:
 		return new ShowInventoryItem();
-	case 0x8C:
+	case 150:
 		return new PlayDigiSoundAndDie();
-	case 0x8D:
+	case 151:
 		return new PlayDigiSoundAndDie();
-	case 0x8E:
+	case 152:
 		return new PlaySoundPanFrameAnchorAndDie();
-	case 0x8F:
+	case 153:
 		return new PlaySoundMultiHS();
-	case 0x96:
+	case 160:
 		return new HintSystem();
 	default:
-		error("Action Record type %i is invalid!", type+0xA);
+		error("Action Record type %i is invalid!", type);
 		return nullptr;
 	}
 }
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index 4ac9477cb81..b6829ee100b 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -546,7 +546,7 @@ bool NancyConsole::Cmd_scanForActionRecordType(int argc, const char **argv) {
 		return true;
 	}
 
-	byte typeID = atoi(argv[1]) + 10;
+	byte typeID = atoi(argv[1]);
 
 	Common::Array<Common::String> list;
 	g_nancy->_resource->list((argc == 2 ? "ciftree" : argv[2]), list, ResourceManager::kResTypeScript);


Commit: 203d4fa5dc2f0db65d2f11d3d71d799c30ea431b
    https://github.com/scummvm/scummvm/commit/203d4fa5dc2f0db65d2f11d3d71d799c30ea431b
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:35+03:00

Commit Message:
NANCY: Implement Overlay action record

Implemented the Overlay action record, which is the
upgraded version of PlayIntStaticBitmapAnim that appears
from nancy 2 and onward.

Changed paths:
  A engines/nancy/action/overlay.cpp
  A engines/nancy/action/overlay.h
  R engines/nancy/action/staticbitmapanim.cpp
  R engines/nancy/action/staticbitmapanim.h
    engines/nancy/action/arfactory.cpp
    engines/nancy/commontypes.cpp
    engines/nancy/module.mk


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index a49bae4a118..31e7a8a9f79 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -23,7 +23,7 @@
 #include "engines/nancy/action/primaryvideo.h"
 #include "engines/nancy/action/secondaryvideo.h"
 #include "engines/nancy/action/secondarymovie.h"
-#include "engines/nancy/action/staticbitmapanim.h"
+#include "engines/nancy/action/overlay.h"
 #include "engines/nancy/action/orderingpuzzle.h"
 #include "engines/nancy/action/rotatinglockpuzzle.h"
 #include "engines/nancy/action/telephone.h"
@@ -63,9 +63,9 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 	case 53:
 		return new PlaySecondaryMovie();
 	case 54:
-		return new PlayStaticBitmapAnimation(false); // PlayStaticBitmapAnimation
+		return new Overlay(false); // PlayStaticBitmapAnimation
 	case 55:
-		return new PlayStaticBitmapAnimation(true); // PlayIntStaticBitmapAnimation
+		return new Overlay(true); // PlayIntStaticBitmapAnimation
 	case 60:
 		return new MapCall();
 	case 61:
diff --git a/engines/nancy/action/staticbitmapanim.cpp b/engines/nancy/action/overlay.cpp
similarity index 54%
rename from engines/nancy/action/staticbitmapanim.cpp
rename to engines/nancy/action/overlay.cpp
index 2a1f0f4cd2a..19247e3f08a 100644
--- a/engines/nancy/action/staticbitmapanim.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -24,65 +24,77 @@
 #include "engines/nancy/resource.h"
 #include "engines/nancy/util.h"
 
-#include "engines/nancy/action/staticbitmapanim.h"
+#include "engines/nancy/action/overlay.h"
 
 #include "engines/nancy/state/scene.h"
 
+#include "common/serializer.h"
+
 namespace Nancy {
 namespace Action {
 
-void PlayStaticBitmapAnimation::init() {
+void Overlay::init() {
 	g_nancy->_resource->loadImage(_imageName, _fullSurface);
 
-	setFrame(0);
+	setFrame(_firstFrame);
 
 	RenderObject::init();
 }
 
-void PlayStaticBitmapAnimation::readData(Common::SeekableReadStream &stream) {
-	readFilename(stream, _imageName);
-
-	stream.skip(0x2);
-	_transparency = stream.readUint16LE();
-	_animationSceneChange = stream.readUint16LE();
-	_playDirection = stream.readUint16LE();
-	_loop = stream.readUint16LE();
-	_firstFrame = stream.readUint16LE();
-	_loopFirstFrame = stream.readUint16LE();
-	_loopLastFrame = stream.readUint16LE();
+void Overlay::readData(Common::SeekableReadStream &stream) {
+	Common::Serializer ser(&stream, nullptr);
+	ser.setVersion(g_nancy->getGameType());
+
+	uint16 numSrcRects;
+
+	readFilename(ser, _imageName);
+	ser.skip(2);
+	ser.syncAsUint16LE(_transparency);
+	ser.syncAsUint16LE(_hasSceneChange);
+
+	ser.syncAsUint16LE(_enableHotspot, kGameTypeNancy2);
+	ser.syncAsUint16LE(_z, kGameTypeNancy2);
+	ser.syncAsUint16LE(_overlayType, kGameTypeNancy2);
+	ser.syncAsUint16LE(numSrcRects, kGameTypeNancy2);
+
+	ser.syncAsUint16LE(_playDirection);
+	ser.syncAsUint16LE(_loop);
+	ser.syncAsUint16LE(_firstFrame);
+	ser.syncAsUint16LE(_loopFirstFrame);
+	ser.syncAsUint16LE(_loopLastFrame);
 	_frameTime = Common::Rational(1000, stream.readUint16LE()).toInt();
-	_z = stream.readUint16LE();
+	ser.syncAsUint16LE(_z, kGameTypeNancy1, kGameTypeNancy1);
 
-	if (_isInterruptible) {
-		_interruptCondition.label = stream.readSint16LE();
-		_interruptCondition.flag = stream.readUint16LE();
-	} else {
-		_interruptCondition.label = kEvNoEvent;
-		_interruptCondition.flag = kEvNotOccurred;
+	if (ser.getVersion() > kGameTypeNancy1) {
+		_isInterruptible = true;
 	}
 
+	if (_isInterruptible) {
+			ser.syncAsSint16LE(_interruptCondition.label);
+			ser.syncAsUint16LE(_interruptCondition.flag);
+		} else {
+			_interruptCondition.label = kEvNoEvent;
+			_interruptCondition.flag = kEvNotOccurred;
+		}
+
 	_sceneChange.readData(stream);
-	_triggerFlags.readData(stream);
+	_flagsOnTrigger.readData(stream);
 	_sound.read(stream, SoundDescription::kNormal);
 	uint numViewportFrames = stream.readUint16LE();
 
-	_srcRects.reserve(_loopLastFrame - _firstFrame);
-	for (uint i = _firstFrame; i <= _loopLastFrame; ++i) {
-		_srcRects.push_back(Common::Rect());
-		readRect(stream, _srcRects[i]);
+	if (_overlayType == kPlayOverlayAnimated) {
+		numSrcRects = _loopLastFrame - _firstFrame + 1;
 	}
 
-	_bitmaps.reserve(numViewportFrames);
-	for (uint i = 0; i < numViewportFrames; ++i) {
-		_bitmaps.push_back(BitmapDescription());
-		BitmapDescription &rects = _bitmaps.back();
-		rects.frameID = stream.readUint16LE();
-		readRect(stream, rects.src);
-		readRect(stream, rects.dest);
+	readRectArray(ser, _srcRects, numSrcRects);
+
+	_bitmaps.resize(numViewportFrames);
+	for (auto &bm : _bitmaps) {
+		bm.readData(stream);
 	}
 }
 
-void PlayStaticBitmapAnimation::execute() {
+void Overlay::execute() {
 	uint32 _currentFrameTime = g_nancy->getTotalPlayTime();
 	switch (_state) {
 	case kBegin:
@@ -94,11 +106,11 @@ void PlayStaticBitmapAnimation::execute() {
 		// fall through
 	case kRun: {
 		// Check the timer to see if we need to draw the next animation frame
-		if (_nextFrameTime <= _currentFrameTime) {
+		if (_overlayType == kPlayOverlayAnimated && _nextFrameTime <= _currentFrameTime) {
 			// World's worst if statement
 			if (NancySceneState.getEventFlag(_interruptCondition) ||
-				(	(((_currentFrame == _loopLastFrame) && (_playDirection == kPlayAnimationForward) && (_loop == kPlayAnimationOnce)) ||
-					((_currentFrame == _loopFirstFrame) && (_playDirection == kPlayAnimationReverse) && (_loop == kPlayAnimationOnce))) &&
+				(	(((_currentFrame == _loopLastFrame) && (_playDirection == kPlayOverlayForward) && (_loop == kPlayOverlayOnce)) ||
+					((_currentFrame == _loopFirstFrame) && (_playDirection == kPlayOverlayReverse) && (_loop == kPlayOverlayOnce))) &&
 						!g_nancy->_sound->isSoundPlaying(_sound))	) {
 
 				_state = kActionTrigger;
@@ -117,26 +129,30 @@ void PlayStaticBitmapAnimation::execute() {
 				if (_currentViewportFrame != newFrame) {
 					_currentViewportFrame = newFrame;
 
+					setVisible(false);
+
 					for (uint i = 0; i < _bitmaps.size(); ++i) {
 						if (_currentViewportFrame == _bitmaps[i].frameID) {
-							_screenPosition = _bitmaps[i].dest;
+							moveTo(_bitmaps[i].dest);
+							setVisible(true);
 							break;
 						}
 					}
 				}
 
 				_nextFrameTime = _currentFrameTime + _frameTime;
-				setFrame(_currentFrame);
 
-				if (_playDirection == kPlayAnimationReverse) {
-					--_currentFrame;
-					_currentFrame = _currentFrame < _loopFirstFrame ? _loopLastFrame : _currentFrame;
-					return;
+				uint16 nextFrame = _currentFrame;
+
+				if (_playDirection == kPlayOverlayReverse) {
+					--nextFrame;
+					nextFrame = nextFrame < _loopFirstFrame ? _loopLastFrame : nextFrame;
 				} else {
-					++_currentFrame;
-					_currentFrame = _currentFrame > _loopLastFrame ? _loopFirstFrame : _currentFrame;
-					return;
+					++nextFrame;
+					nextFrame = nextFrame > _loopLastFrame ? _loopFirstFrame : nextFrame;
 				}
+
+				setFrame(nextFrame);
 			}
 		} else {
 			// Check if we've moved the viewport
@@ -145,9 +161,24 @@ void PlayStaticBitmapAnimation::execute() {
 			if (_currentViewportFrame != newFrame) {
 				_currentViewportFrame = newFrame;
 
+				setVisible(false);
+				_hasHotspot = false;
+
 				for (uint i = 0; i < _bitmaps.size(); ++i) {
 					if (_currentViewportFrame == _bitmaps[i].frameID) {
-						_screenPosition = _bitmaps[i].dest;
+						moveTo(_bitmaps[i].dest);
+						setVisible(true);
+
+						// In static mode every "animation" frame corresponds to a viewport frame
+						if (_overlayType == kPlayOverlayStatic) {
+							setFrame(i);
+
+							if (_enableHotspot) {
+								_hotspot = _screenPosition;
+								_hasHotspot = true;
+							}
+						}
+
 						break;
 					}
 				}
@@ -157,8 +188,8 @@ void PlayStaticBitmapAnimation::execute() {
 		break;
 	}
 	case kActionTrigger:
-		_triggerFlags.execute();
-		if (_animationSceneChange == kPlayAnimationSceneChange) {
+		_flagsOnTrigger.execute();
+		if (_hasSceneChange == kPlayOverlaySceneChange) {
 			NancySceneState.changeScene(_sceneChange);
 			finishExecution();
 		}
@@ -166,17 +197,29 @@ void PlayStaticBitmapAnimation::execute() {
 	}
 }
 
-void PlayStaticBitmapAnimation::onPause(bool pause) {
+void Overlay::onPause(bool pause) {
 	if (!pause) {
 		registerGraphics();
 	}
 }
 
-void PlayStaticBitmapAnimation::setFrame(uint frame) {
+Common::String Overlay::getRecordTypeName() const {
+	if (g_nancy->getGameType() <= kGameTypeNancy1) {
+		if (_isInterruptible) {
+			return "PlayIntStaticBitmapAnimation";
+		} else {
+			return "PlayStaticBitmapAnimation";
+		}
+	} else {
+		return "Overlay";
+	}
+}
+
+void Overlay::setFrame(uint frame) {
 	_currentFrame = frame;
 	_drawSurface.create(_fullSurface, _srcRects[frame]);
 
-	setTransparent(_transparency == kPlayAnimationPlain);
+	setTransparent(_transparency == kPlayOverlayPlain);
 
 	_needsRedraw = true;
 }
diff --git a/engines/nancy/action/staticbitmapanim.h b/engines/nancy/action/overlay.h
similarity index 50%
rename from engines/nancy/action/staticbitmapanim.h
rename to engines/nancy/action/overlay.h
index 41a88acaadd..cb66adad9eb 100644
--- a/engines/nancy/action/staticbitmapanim.h
+++ b/engines/nancy/action/overlay.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef NANCY_ACTION_STATICBITMAPANIM_H
-#define NANCY_ACTION_STATICBITMAPANIM_H
+#ifndef NANCY_ACTION_OVERLAY_H
+#define NANCY_ACTION_OVERLAY_H
 
 #include "engines/nancy/renderobject.h"
 
@@ -29,26 +29,35 @@
 namespace Nancy {
 namespace Action {
 
-// ActionRecord subclass describing a short "flipbook" animation from a single bitmap
-// Also supports sound and getting interrupted by an event flag.
-// This class covers both the PlayStaticBitmapAnimation and PlayIntStaticBitmapAnimation
-// action record types, whose functionality is nearly identical
-class PlayStaticBitmapAnimation : public ActionRecord, public RenderObject {
+// ActionRecord describing an overlay on top of the viewport.
+// That overlay can be either a short animation, or a static bitmap
+// that changes depending on the current viewport frame.
+// This class covers three different ActionRecord types:
+// - PlayStaticBitmapAnimation: nancy1 only, does not support static mode
+// - PlayIntStaticBitmapAnimation: nancy1 only, same as above but supports being interrupted by an event flag
+// - Overlay: nancy2 and above, supports static mode
+class Overlay : public ActionRecord, public RenderObject {
 public:
-	static const byte kPlayAnimationPlain			= 1;
-	static const byte kPlayAnimationTransparent		= 2;
+	static const byte kPlayOverlayPlain				= 1;
+	static const byte kPlayOverlayTransparent		= 2;
 
-	static const byte kPlayAnimationSceneChange		= 1;
-	static const byte kPlayAnimationNoSceneChange 	= 2;
+	static const byte kPlayOverlaySceneChange		= 1;
+	static const byte kPlayOverlayNoSceneChange 	= 2;
 
-	static const byte kPlayAnimationOnce			= 1;
-	static const byte kPlayAnimationLoop			= 2;
+	static const byte kPlayOverlayStatic			= 1;
+	static const byte kPlayOverlayAnimated			= 2;
 
-	static const byte kPlayAnimationForward			= 1;
-	static const byte kPlayAnimationReverse			= 2;
+	static const byte kPlayOverlayOnce				= 1;
+	static const byte kPlayOverlayLoop				= 2;
 
-	PlayStaticBitmapAnimation(bool interruptible) : RenderObject(7), _isInterruptible(interruptible) {}
-	virtual ~PlayStaticBitmapAnimation() { _fullSurface.free(); }
+	static const byte kPlayOverlayForward			= 1;
+	static const byte kPlayOverlayReverse			= 2;
+
+	static const byte kPlayOverlayWithHotspot		= 1;
+	static const byte kPlayOverlayNoHotspot			= 2;
+
+	Overlay(bool interruptible) : RenderObject(7), _isInterruptible(interruptible) {}
+	virtual ~Overlay() { _fullSurface.free(); }
 
 	void init() override;
 
@@ -58,17 +67,19 @@ public:
 
 	Common::String _imageName;
 
-	uint16 _transparency = kPlayAnimationPlain; // 0xC
-	uint16 _animationSceneChange = kPlayAnimationSceneChange; // 0xE
-	uint16 _playDirection = kPlayAnimationForward; // 0x10
-	uint16 _loop = kPlayAnimationOnce; // 0x12
-	uint16 _firstFrame = 0; // 0x14
-	uint16 _loopFirstFrame = 0; // 0x16
-	uint16 _loopLastFrame = 0; // 0x18
+	uint16 _transparency = kPlayOverlayPlain;
+	uint16 _hasSceneChange = kPlayOverlaySceneChange;
+	uint16 _enableHotspot = kPlayOverlayNoHotspot;
+	uint16 _overlayType = kPlayOverlayAnimated;
+	uint16 _playDirection = kPlayOverlayForward;
+	uint16 _loop = kPlayOverlayOnce;
+	uint16 _firstFrame = 0;
+	uint16 _loopFirstFrame = 0;
+	uint16 _loopLastFrame = 0;
 	Time _frameTime;
-	FlagDescription _interruptCondition; // 0x1E
+	FlagDescription _interruptCondition;
 	SceneChangeDescription _sceneChange;
-	MultiEventFlagDescription _triggerFlags; // 0x2A
+	MultiEventFlagDescription _flagsOnTrigger; // 0x2A
 
 	Nancy::SoundDescription _sound; // 0x52
 
@@ -84,7 +95,7 @@ public:
 	bool _isInterruptible;
 
 protected:
-	Common::String getRecordTypeName() const override { return _isInterruptible ? "PlayIntStaticBitmapAnimation" : "PlayStaticBitmapAnimation"; }
+	Common::String getRecordTypeName() const override;
 	bool isViewportRelative() const override { return true; }
 
 	void setFrame(uint frame);
@@ -95,4 +106,4 @@ protected:
 } // End of namespace Action
 } // End of namespace Nancy
 
-#endif // NANCY_ACTION_STATICBITMAPANIM_H
+#endif // NANCY_ACTION_OVERLAY_H
diff --git a/engines/nancy/commontypes.cpp b/engines/nancy/commontypes.cpp
index 1d5473d4672..9d492d2b77d 100644
--- a/engines/nancy/commontypes.cpp
+++ b/engines/nancy/commontypes.cpp
@@ -21,6 +21,7 @@
 
 #include "engines/nancy/commontypes.h"
 #include "engines/nancy/util.h"
+#include "engines/nancy/nancy.h"
 
 #include "engines/nancy/state/scene.h"
 
@@ -43,7 +44,12 @@ void HotspotDescription::readData(Common::SeekableReadStream &stream) {
 }
 
 void BitmapDescription::readData(Common::SeekableReadStream &stream) {
-	frameID = stream.readUint16LE();
+	if (g_nancy->getGameType() <= kGameTypeNancy1) {
+		frameID = stream.readUint16LE();
+	} else {
+		frameID = stream.readUint32LE();
+	}
+	
 	readRect(stream, src);
 	readRect(stream, dest);
 }
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index 1d062e9081f..83034d57663 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -13,7 +13,7 @@ MODULE_OBJS = \
   action/secondarymovie.o \
   action/secondaryvideo.o \
   action/sliderpuzzle.o \
-  action/staticbitmapanim.o \
+  action/overlay.o \
   action/telephone.o \
   ui/fullscreenimage.o \
   ui/animatedbutton.o \


Commit: e76e3c3f1f1ff6b706d1a28701c65c62e5f1de5a
    https://github.com/scummvm/scummvm/commit/e76e3c3f1f1ff6b706d1a28701c65c62e5f1de5a
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:35+03:00

Commit Message:
NANCY: Correctly load INV chunk in nancy2

Added code to load the new data found in the INV chunk.,

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 1c1f6d75d93..82df0bc6a25 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -116,24 +116,66 @@ INV::INV(Common::SeekableReadStream *chunkStream) {
 	readFilename(s, inventoryBoxIconsImageName);
 	readFilename(s, inventoryCursorsImageName);
 
-	s.skip(0x4); // inventory box icons surface w/h
-	s.skip(0x4); // inventory cursors surface w/h
+	s.skip(0x4, kGameTypeVampire, kGameTypeNancy1); // inventory box icons surface w/h
+	s.skip(0x4, kGameTypeVampire, kGameTypeNancy1); // inventory cursors surface w/h
 
 	s.skip(0x10); // unknown rect, same size as a hotspot
 
-	byte itemName[20];
-	uint itemNameLength = g_nancy->getGameType() == kGameTypeVampire ? 15 : 20;
+	byte textBuf[60];
+
+	if (s.getVersion() >= kGameTypeNancy2) {
+		cantSound.read(*chunkStream, SoundDescription::kNormal);
+		s.syncBytes(textBuf, 60);
+		textBuf[59] = '\0';
+		cantText = (char *)textBuf;
+	}
+
+	uint itemNameLength;
+	switch (s.getVersion()) {
+		case kGameTypeVampire :
+			itemNameLength = 15;
+			break;
+		case kGameTypeNancy1 :
+			itemNameLength = 20;
+			break;
+		case kGameTypeNancy2 :
+			// fall through
+		default:
+			itemNameLength = 48;
+			break;
+	}
 
 	uint16 numItems = g_nancy->getStaticData().numItems;
 	itemDescriptions.resize(numItems);
 	for (uint i = 0; i < numItems; ++i) {
 		ItemDescription &item = itemDescriptions[i];
 		
-		s.syncBytes(itemName, itemNameLength);
-		itemName[itemNameLength - 1] = '\0';
-		item.name = (char *)itemName;
+		s.syncBytes(textBuf, itemNameLength);
+		textBuf[itemNameLength - 1] = '\0';
+		item.name = (char *)textBuf;
+
 		s.syncAsUint16LE(item.keepItem);
 		readRect(s, item.sourceRect);
+		readRect(s, item.highlightedSourceRect, kGameTypeNancy2);
+
+		if (s.getVersion() == kGameTypeNancy2) {
+			s.syncBytes(textBuf, 60);
+			textBuf[59] = '\0';
+			item.specificCantText = (char *)textBuf;
+
+			s.syncBytes(textBuf, 60);
+			textBuf[59] = '\0';
+			item.generalCantText = (char *)textBuf;
+
+			item.specificCantSound.read(*chunkStream, SoundDescription::kNormal);
+			item.generalCantSound.read(*chunkStream, SoundDescription::kNormal);
+		} else if (s.getVersion() >= kGameTypeNancy3) {
+			s.syncBytes(textBuf, 60);
+			textBuf[59] = '\0';
+			item.specificCantText = (char *)textBuf;
+
+			item.specificCantSound.read(*chunkStream, SoundDescription::kNormal);
+		}
 	}
 
 	delete chunkStream;
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index 5227adb8513..3d195bee912 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -69,6 +69,12 @@ struct INV {
 		Common::String name;
 		byte keepItem;
 		Common::Rect sourceRect;
+		Common::Rect highlightedSourceRect;
+
+		Common::String specificCantText;
+		Common::String generalCantText;
+		SoundDescription specificCantSound;
+		SoundDescription generalCantSound;
 	};
 
 	INV(Common::SeekableReadStream *chunkStream);
@@ -87,6 +93,9 @@ struct INV {
 	Common::String inventoryBoxIconsImageName;
 	Common::String inventoryCursorsImageName;
 
+	SoundDescription cantSound;
+	Common::String cantText;
+
 	Common::Array<ItemDescription> itemDescriptions;
 };
 


Commit: 9b1c62e4892e74c881d8154be305a324e8538333
    https://github.com/scummvm/scummvm/commit/9b1c62e4892e74c881d8154be305a324e8538333
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:35+03:00

Commit Message:
NANCY: Add stub for SpecialEffect action record

Changed paths:
    engines/nancy/action/arfactory.cpp
    engines/nancy/action/recordtypes.cpp
    engines/nancy/action/recordtypes.h


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index 31e7a8a9f79..7f52edcbf22 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -33,6 +33,8 @@
 
 #include "engines/nancy/state/scene.h"
 
+#include "engines/nancy/nancy.h"
+
 namespace Nancy {
 namespace Action {
 
@@ -53,7 +55,12 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 	case 21:
 		return new PaletteNextScene();
 	case 40:
-		return new LightningOn();
+		if (g_nancy->getGameType() < kGameTypeNancy2) {
+			// Only used in TVD
+			return new LightningOn();
+		} else {
+			return new SpecialEffect();
+		}		
 	case 50:
 		return new PlayPrimaryVideoChan0();
 	case 51:
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index a004477b1ce..e6509a35c55 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -206,6 +206,10 @@ void LightningOn::readData(Common::SeekableReadStream &stream) {
 	stream.skip(4);
 }
 
+void SpecialEffect::readData(Common::SeekableReadStream &stream) {
+	stream.skip(5);
+}
+
 void LightningOn::execute() {
 	NancySceneState.beginLightning(_distance, _pulseTime, _rgbPercent);
 	_isDone = true;
diff --git a/engines/nancy/action/recordtypes.h b/engines/nancy/action/recordtypes.h
index 5d371711015..f60f22e7700 100644
--- a/engines/nancy/action/recordtypes.h
+++ b/engines/nancy/action/recordtypes.h
@@ -130,6 +130,14 @@ protected:
 	Common::String getRecordTypeName() const override { return "LightningOn"; }
 };
 
+class SpecialEffect : public Unimplemented {
+public:
+	void readData(Common::SeekableReadStream &stream) override;
+
+protected:
+	Common::String getRecordTypeName() const override { return "SpecialEffect"; }
+};
+
 class MapCall : public ActionRecord {
 public:
 	void readData(Common::SeekableReadStream &stream) override;


Commit: 2888248e7ed868582814ee798aacfaf630b879e5
    https://github.com/scummvm/scummvm/commit/2888248e7ed868582814ee798aacfaf630b879e5
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:36+03:00

Commit Message:
NANCY: Add workaround for broken Overlay

Changed paths:
    engines/nancy/action/overlay.cpp


diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index 19247e3f08a..5ff6dfad94b 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -217,7 +217,17 @@ Common::String Overlay::getRecordTypeName() const {
 
 void Overlay::setFrame(uint frame) {
 	_currentFrame = frame;
-	_drawSurface.create(_fullSurface, _srcRects[frame]);
+	
+	// Workaround for the fireplace in nancy2 scene 2491,
+	// where one of the rects is invalid. Assumes all
+	// rects in a single animation have the same dimensions
+	Common::Rect srcRect = _srcRects[frame];
+	if (!srcRect.isValidRect()) {
+		srcRect.setWidth(_srcRects[0].width());
+		srcRect.setHeight(_srcRects[0].height());
+	}
+
+	_drawSurface.create(_fullSurface, srcRect);
 
 	setTransparent(_transparency == kPlayOverlayPlain);
 


Commit: 50a08027aba5729884ff95c4832ce1ce3d15a139
    https://github.com/scummvm/scummvm/commit/50a08027aba5729884ff95c4832ce1ce3d15a139
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:36+03:00

Commit Message:
NANCY: Implement ClosedCaptioning dependency

Implemented the ClosedCaptioning action record
dependency type introduced in nancy2.

Changed paths:
    engines/nancy/action/actionmanager.cpp
    engines/nancy/action/actionrecord.h


diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index 90952714467..a2346cfd270 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "common/serializer.h"
+#include "common/config-manager.h"
 
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/input.h"
@@ -29,7 +30,6 @@
 #include "engines/nancy/action/actionrecord.h"
 
 #include "engines/nancy/state/scene.h"
-
 namespace Nancy {
 namespace Action {
 
@@ -309,6 +309,17 @@ void ActionManager::processActionRecords() {
 							dep.satisfied = true;
 						}
 
+						break;
+					case DependencyType::kClosedCaptioning:
+						if (ConfMan.getBool("subtitles")) {
+							if (dep.condition == 2) {
+								dep.satisfied = true;
+							}
+						} else {
+							if (dep.condition == 1) {
+								dep.satisfied = true;
+							}
+						}
 						break;
 					default:
 						warning("Unimplemented Dependency type %i", (int)dep.type);
diff --git a/engines/nancy/action/actionrecord.h b/engines/nancy/action/actionrecord.h
index bbca62d2b87..327eff5153a 100644
--- a/engines/nancy/action/actionrecord.h
+++ b/engines/nancy/action/actionrecord.h
@@ -55,7 +55,7 @@ enum struct DependencyType : byte {
 	kTimerLessThanDependencyTime	= 13,
 	kTimerGreaterThanDependencyTime	= 14,
 	kDifficultyLevel				= 15,
-	kClosedCaptioning				= 16,	// Not implemented
+	kClosedCaptioning				= 16,
 	kSound							= 17,	// Not implemented
 	kOpenParentheses				= 18,	// Not implemented
 	kCloseParentheses				= 19	// Not implemented


Commit: 0befb73ecbe1959e943000daa6095c291466ba2b
    https://github.com/scummvm/scummvm/commit/0befb73ecbe1959e943000daa6095c291466ba2b
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:36+03:00

Commit Message:
NANCY: Implement TextBoxWrite action record

Changed paths:
    engines/nancy/action/recordtypes.cpp
    engines/nancy/action/recordtypes.h


diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index e6509a35c55..40824c4da96 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -277,11 +277,31 @@ void MapCallHotMultiframe::execute() {
 
 void TextBoxWrite::readData(Common::SeekableReadStream &stream) {
 	uint16 size = stream.readUint16LE();
-	stream.skip(size);
 
 	if (size > 10000) {
 		error("Action Record atTextboxWrite has too many text box chars: %d", size);
 	}
+
+	char *buf = new char[size];
+	stream.read(buf, size);
+	buf[size - 1] = '\0';
+	_text = buf;
+
+	delete[] buf;
+}
+
+TextBoxWrite::~TextBoxWrite() {
+	NancySceneState.setShouldClearTextbox(true);
+	NancySceneState.getTextbox().setVisible(false);
+}
+
+void TextBoxWrite::execute() {
+	auto &tb = NancySceneState.getTextbox();
+	tb.clear();
+	tb.addTextLine(_text);
+	tb.setVisible(true);
+	NancySceneState.setShouldClearTextbox(false);
+	finishExecution();
 }
 
 void TextBoxClear::readData(Common::SeekableReadStream &stream) {
diff --git a/engines/nancy/action/recordtypes.h b/engines/nancy/action/recordtypes.h
index f60f22e7700..9a217a848fe 100644
--- a/engines/nancy/action/recordtypes.h
+++ b/engines/nancy/action/recordtypes.h
@@ -171,9 +171,14 @@ protected:
 	Common::String getRecordTypeName() const override { return "MapCallHotMultiframe"; }
 };
 
-class TextBoxWrite : public Unimplemented {
+class TextBoxWrite : public ActionRecord {
 public:
+	virtual ~TextBoxWrite();
+
 	void readData(Common::SeekableReadStream &stream) override;
+	void execute() override;
+
+	Common::String _text;
 
 protected:
 	Common::String getRecordTypeName() const override { return "TextBoxWrite"; }


Commit: 4e734c4778dfd3104b89ed3ad7d26f1ea102b990
    https://github.com/scummvm/scummvm/commit/4e734c4778dfd3104b89ed3ad7d26f1ea102b990
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:37+03:00

Commit Message:
NANCY: Correct viewport panning

Fixed an issue where the viewport would wrap around once
even when set to kPanLeftRight mode.

Changed paths:
    engines/nancy/ui/viewport.cpp


diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 7dcbf55fa14..83f3d03e48c 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -186,6 +186,8 @@ void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint vert
 	_videoFormat = format;
 
 	enableEdges(kUp | kDown | kLeft | kRight);
+	
+	_panningType = panningType;
 
 	setFrame(frameNr);
 	setVerticalScroll(verticalScroll);
@@ -197,7 +199,6 @@ void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint vert
 
 	_movementLastFrame = 0;
 	_nextMovementTime = 0;
-	_panningType = panningType;
 }
 
 void Viewport::setFrame(uint frameNr) {


Commit: 82d41b17cdeaacca045ce57665976ec89de09489
    https://github.com/scummvm/scummvm/commit/82d41b17cdeaacca045ce57665976ec89de09489
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-04-13T21:20:37+03:00

Commit Message:
NANCY: Show virtual keyboard during password puzzle

Changed paths:
    engines/nancy/action/passwordpuzzle.cpp


diff --git a/engines/nancy/action/passwordpuzzle.cpp b/engines/nancy/action/passwordpuzzle.cpp
index ba131d67048..f85faf01257 100644
--- a/engines/nancy/action/passwordpuzzle.cpp
+++ b/engines/nancy/action/passwordpuzzle.cpp
@@ -77,6 +77,7 @@ void PasswordPuzzle::execute() {
 	case kBegin:
 		init();
 		registerGraphics();
+		g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
 		_nextBlinkTime = g_nancy->getTotalPlayTime() + _cursorBlinkTime;
 		_state = kRun;
 		// fall through
@@ -156,6 +157,8 @@ void PasswordPuzzle::execute() {
 			NancySceneState.setEventFlag(_flagOnSolve.label);
 			break;
 		}
+		
+		g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
 
 		finishExecution();
 	}




More information about the Scummvm-git-logs mailing list