[Scummvm-git-logs] scummvm master -> d4d40270c233f3b19ee404cc27782991163197d2

sev- noreply at scummvm.org
Fri Nov 18 15:28:13 UTC 2022


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

Summary:
8f15436896 DIRECTOR: Include more cast information in debug output
9a10fe51d3 DIRECTOR: Provide live channel information for current frame
90e8341f67 DIRECTOR: Set next frame time before executing scripts
1524ee3615 DIRECTOR: Fix coloring of 1-bit bitmaps
665a76536e DIRECTOR: Fix setter for "the rect of sprite"
93262a99fb DIRECTOR: Add memory guardrails for inkBlitSurface
f36205be67 DIRECTOR: Reduce Lingo warning spam
d4d40270c2 DIRECTOR: Fix file location for P.A.W.S.


Commit: 8f15436896e1454dda5db896d62c4cd77f61095f
    https://github.com/scummvm/scummvm/commit/8f15436896e1454dda5db896d62c4cd77f61095f
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Include more cast information in debug output

Changed paths:
    engines/director/cast.cpp
    engines/director/castmember.cpp
    engines/director/castmember.h


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 4f1a9ff3a22..245aee83e44 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -1517,10 +1517,16 @@ Common::String Cast::formatCastSummary(int castId = -1) {
 			continue;
 		CastMember *castMember = getCastMember(*it);
 		CastMemberInfo *castMemberInfo = getCastMemberInfo(*it);
-		result += Common::String::format("%d: type=%s, name=\"%s\"\n",
+		Common::String info = castMember->formatInfo();
+		result += Common::String::format("%5d: type=%s, name=\"%s\"",
 			*it, castTypeToString(castMember->_type).c_str(),
 			castMemberInfo ? castMemberInfo->name.c_str() : ""
 		);
+		if (!info.empty()) {
+			result += ", ";
+			result += info;
+		}
+		result += "\n";
 	}
 	return result;
 }
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index 847401d463c..8acdcdd8d3a 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -385,6 +385,17 @@ Graphics::Surface *BitmapCastMember::getMatte(Common::Rect &bbox) {
 	return _matte ? _matte->getMask() : nullptr;
 }
 
+Common::String BitmapCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, foreColor: %d, backColor: %d, regX: %d, regY: %d, pitch: %d, bitsPerPixel: %d",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		getForeColor(), getBackColor(),
+		_regX, _regY, _pitch, _bitsPerPixel
+	);
+}
 
 /////////////////////////////////////
 // DigitalVideo
@@ -665,6 +676,20 @@ void DigitalVideoCastMember::setFrameRate(int rate) {
 	warning("STUB: DigitalVideoCastMember::setFrameRate(%d)", rate);
 }
 
+Common::String DigitalVideoCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, filename: \"%s\", duration: %d, enableVideo: %d, enableSound: %d, looping: %d, crop: %d, center: %d, showControls: %d",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		_filename.c_str(), _duration,
+		_enableVideo, _enableSound,
+		_looping, _crop, _center, _showControls
+	);
+}
+
+
 /////////////////////////////////////
 // MovieCasts
 /////////////////////////////////////
@@ -690,6 +715,17 @@ MovieCastMember::MovieCastMember(Cast *cast, uint16 castId, Common::SeekableRead
 
 }
 
+Common::String MovieCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, enableScripts: %d, enableSound: %d, looping: %d, crop: %d, center: %d",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		_enableScripts, _enableSound, _looping,
+		_crop, _center
+	);
+}
 
 /////////////////////////////////////
 // Film loops
@@ -907,6 +943,17 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
 
 }
 
+Common::String FilmLoopCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, frameCount: %d, subchannelCount: %d, enableSound: %d, looping: %d, crop: %d, center: %d",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		_frames.size(), _subchannels.size(), _enableSound, _looping,
+		_crop, _center
+	);
+}
 
 /////////////////////////////////////
 // Sound
@@ -924,6 +971,11 @@ SoundCastMember::~SoundCastMember() {
 		delete _audio;
 }
 
+Common::String SoundCastMember::formatInfo() {
+	return Common::String::format(
+		"looping: %d", _looping
+	);
+}
 
 /////////////////////////////////////
 // Text
@@ -1243,6 +1295,19 @@ void TextCastMember::updateFromWidget(Graphics::MacWidget *widget) {
 	}
 }
 
+Common::String TextCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, foreColor: %d, backColor: %d, editable: %d, text: \"%s\"",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		getForeColor(), getBackColor(),
+		_editable, _ptext.encode().c_str()
+	);
+
+}
+
 
 /////////////////////////////////////
 // Shape
@@ -1312,6 +1377,18 @@ void ShapeCastMember::setForeColor(uint32 fgCol) {
 	_modified = true;
 }
 
+Common::String ShapeCastMember::formatInfo() {
+	return Common::String::format(
+		"initialRect: %dx%d@%d,%d, boundingRect: %dx%d@%d,%d, foreColor: %d, backColor: %d, shapeType: %d, pattern: %d, fillType: %d, lineThickness: %d, lineDirection: %d, ink: %d",
+		_initialRect.width(), _initialRect.height(),
+		_initialRect.left, _initialRect.top,
+		_boundingRect.width(), _boundingRect.height(),
+		_boundingRect.left, _boundingRect.top,
+		getForeColor(), getBackColor(),
+		_shapeType, _pattern, _fillType,
+		_lineThickness, _lineDirection, _ink
+	);
+}
 
 /////////////////////////////////////
 // Script
diff --git a/engines/director/castmember.h b/engines/director/castmember.h
index 90826da1958..16de734d206 100644
--- a/engines/director/castmember.h
+++ b/engines/director/castmember.h
@@ -96,6 +96,8 @@ public:
 	// release the control to widget, this happens when we are changing sprites. Because we are having the new cast member and the old one shall leave
 	void releaseWidget() { _widget = nullptr; }
 
+	virtual Common::String formatInfo() { return Common::String(); };
+
 	CastType _type;
 	Common::Rect _initialRect;
 	Common::Rect _boundingRect;
@@ -131,6 +133,8 @@ public:
 	Datum getField(int field) override;
 	bool setField(int field, const Datum &value) override;
 
+	Common::String formatInfo() override;
+
 	Image::ImageDecoder *_img;
 	Graphics::Surface *_ditheredImg;
 	Graphics::FloodFill *_matte;
@@ -173,6 +177,8 @@ public:
 	Datum getField(int field) override;
 	bool setField(int field, const Datum &value) override;
 
+	Common::String formatInfo() override;
+
 	Common::String _filename;
 
 	uint32 _vflags;
@@ -215,6 +221,8 @@ public:
 
 	void loadFilmLoopData(Common::SeekableReadStreamEndian &stream);
 
+	Common::String formatInfo() override;
+
 	bool _enableSound;
 	bool _looping;
 	bool _crop;
@@ -228,6 +236,8 @@ class MovieCastMember : public CastMember {
 public:
 	MovieCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
 
+	Common::String formatInfo() override;
+
 	uint32 _flags;
 	bool _looping;
 	bool _enableScripts;
@@ -241,6 +251,8 @@ public:
 	SoundCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
 	~SoundCastMember();
 
+	Common::String formatInfo() override;
+
 	bool _looping;
 	AudioDecoder *_audio;
 };
@@ -253,6 +265,8 @@ public:
 	void setBackColor(uint32 bgCol) override;
 	void setForeColor(uint32 fgCol) override;
 
+	Common::String formatInfo() override;
+
 	ShapeType _shapeType;
 	uint16 _pattern;
 	byte _fillType;
@@ -296,6 +310,8 @@ public:
 	int getTextSize();
 	void setTextSize(int textSize);
 
+	Common::String formatInfo() override;
+
 	SizeType _borderSize;
 	SizeType _gutterSize;
 	SizeType _boxShadow;


Commit: 9a10fe51d3a71505ea9a6ff25ebab7c03f4d50ad
    https://github.com/scummvm/scummvm/commit/9a10fe51d3a71505ea9a6ff25ebab7c03f4d50ad
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Provide live channel information for current frame

Changed paths:
    engines/director/debugger.cpp
    engines/director/score.cpp
    engines/director/score.h


diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index de9fedc059f..ece454253b4 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -230,6 +230,12 @@ bool Debugger::cmdChannels(int argc, const char **argv) {
 
 	int maxSize = (int)score->_frames.size();
 	int frameId = score->getCurrentFrame();
+	if (argc == 1) {
+		debugPrintf("Channel info for current frame %d of %d\n", frameId, maxSize);
+		debugPrintf("%s\n", score->formatChannelInfo().c_str());
+		return true;
+	}
+
 	if (argc == 2)
 		frameId = atoi(argv[1]);
 
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 2080ca5bf6b..638fb72dd16 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1373,4 +1373,41 @@ void Score::loadActions(Common::SeekableReadStreamEndian &stream) {
 	free(scriptRefs);
 }
 
+Common::String Score::formatChannelInfo() {
+	Frame &frame = *_frames[_currentFrame]; 
+	Common::String result;
+	result += Common::String::format("TMPO:   tempo: %d, skipFrameFlag: %d, blend: %d\n",
+		frame._tempo, frame._skipFrameFlag, frame._blend);
+	if (frame._palette.paletteId) {
+		result += Common::String::format("PAL:    paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d\n",
+			frame._palette.paletteId, frame._palette.firstColor, frame._palette.lastColor, frame._palette.flags,
+			frame._palette.cycleCount, frame._palette.speed, frame._palette.frameCount,
+			frame._palette.fade, frame._palette.delay, frame._palette.style);
+	} else {
+		result += Common::String::format("PAL:    paletteId: 000\n");
+	}
+	result += Common::String::format("TRAN:   transType: %d, transDuration: %d, transChunkSize: %d\n",
+		frame._transType, frame._transDuration, frame._transChunkSize);
+	result += Common::String::format("SND: 1  sound1: %d, soundType1: %d\n", frame._sound1.member, frame._soundType1);
+	result += Common::String::format("SND: 2  sound2: %d, soundType2: %d\n", frame._sound2.member, frame._soundType2);
+	result += Common::String::format("LSCR:   actionId: %d\n", frame._actionId.member);
+
+	for (int i = 0; i < frame._numChannels; i++) {
+		Channel &channel = *_channels[i + 1];
+		Sprite &sprite = *channel._sprite;
+		if (sprite._castId.member) {
+			result += Common::String::format("CH: %-3d castId: %s, visible:%d,[inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x, constraint: %d, puppet: %d, stretch: %d\n",
+				i + 1, sprite._castId.asString().c_str(), channel._visible, sprite._inkData,
+				sprite._ink, sprite._trails, sprite._thickness, channel._width, channel._height,
+				channel._currentPoint.x, channel._currentPoint.y,
+				sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3, channel._constraint, sprite._puppet, sprite._stretch);
+		} else {
+			result += Common::String::format("CH: %-3d castId: 000\n", i + 1);
+		}
+	}
+
+	return result;
+
+}
+
 } // End of namespace Director
diff --git a/engines/director/score.h b/engines/director/score.h
index a4d77edee32..dd9f7b21ae7 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -120,6 +120,8 @@ public:
 
 	void playSoundChannel(uint16 frameId, bool puppetOnly);
 
+	Common::String formatChannelInfo();
+
 private:
 	void update();
 	void playQueuedSound();


Commit: 90e8341f67d4184427260af9bdd976cd06e74522
    https://github.com/scummvm/scummvm/commit/90e8341f67d4184427260af9bdd976cd06e74522
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Set next frame time before executing scripts

Previously, frame scripts that called "delay" would have that adjustment
clobbered by Score::update().

Fixes the credits sequence in Nemurenu Yoru no Chiisana Ohanashi.

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/score.cpp


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index eebd12e72b8..6ec65e778f5 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1285,8 +1285,8 @@ void LB::b_nothing(int nargs) {
 
 void LB::b_delay(int nargs) {
 	Datum d = g_lingo->pop();
-
 	g_director->getCurrentMovie()->getScore()->_nextFrameTime = g_system->getMillis() + (float)d.asInt() / 60 * 1000;
+	debugC(5, kDebugLoading, "b_delay(): delaying %d ticks, next frame time at %d", d.asInt(), g_director->getCurrentMovie()->getScore()->_nextFrameTime);
 }
 
 void LB::b_do(int nargs) {
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 638fb72dd16..7b02d12eadc 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -325,6 +325,7 @@ void Score::update() {
 	if (!debugChannelSet(-1, kDebugFast)) {
 		bool keepWaiting = false;
 
+		debugC(8, kDebugLoading, "Score::update(): nextFrameTime: %d, time: %d", _nextFrameTime, g_system->getMillis(false));
 		if (_waitForChannel) {
 			if (_soundManager->isChannelActive(_waitForChannel)) {
 				keepWaiting = true;
@@ -421,7 +422,53 @@ void Score::update() {
 		}
 	}
 
-	debugC(1, kDebugImages, "******************************  Current frame: %d", _currentFrame);
+	byte tempo = _frames[_currentFrame]->_scoreCachedTempo;
+	// puppetTempo is overridden by changes in score tempo
+	if (_frames[_currentFrame]->_tempo || tempo != _lastTempo) {
+		_puppetTempo = 0;
+	} else if (_puppetTempo) {
+		tempo = _puppetTempo;
+	}
+
+	if (tempo) {
+		const bool waitForClickOnly = _vm->getVersion() < 300;
+		const int maxDelay = _vm->getVersion() < 400 ? 120 : 60;
+		if (tempo >= 256 - maxDelay) {
+			// Delay
+			_nextFrameTime = g_system->getMillis() + (256 - tempo) * 1000;
+		} else if (tempo <= 120) {
+			// FPS
+			_currentFrameRate = tempo;
+			_nextFrameTime = g_system->getMillis() + 1000.0 / (float)_currentFrameRate;
+		} else {
+			if (tempo == 128) {
+				_waitForClick = true;
+				_waitForClickCursor = false;
+				renderCursor(_movie->getWindow()->getMousePos());
+			} else if (!waitForClickOnly && tempo == 135) {
+				// Wait for sound channel 1
+				_waitForChannel = 1;
+			} else if (!waitForClickOnly && tempo == 134) {
+				// Wait for sound channel 2
+				_waitForChannel = 2;
+
+			} else if (!waitForClickOnly && tempo >= 136 && tempo <= 135 + _numChannelsDisplayed) {
+				// Wait for a digital video in a channel to finish playing
+				_waitForVideoChannel = tempo - 135;
+			} else {
+				warning("Unhandled tempo instruction: %d", tempo);
+			}
+			_nextFrameTime = g_system->getMillis();
+		}
+	} else {
+		_nextFrameTime = g_system->getMillis() + 1000.0 / (float)_currentFrameRate;
+	}
+	_lastTempo = tempo;
+
+	if (debugChannelSet(-1, kDebugSlow))
+		_nextFrameTime += 1000;
+
+	debugC(1, kDebugLoading, "******************************  Current frame: %d, time: %d", _currentFrame, g_system->getMillis(false));
 	g_debugger->frameHook();
 
 	uint initialCallStackSize = _window->_callstack.size();
@@ -471,51 +518,6 @@ void Score::update() {
 		}
 	}
 
-	byte tempo = _frames[_currentFrame]->_scoreCachedTempo;
-	// puppetTempo is overridden by changes in score tempo
-	if (_frames[_currentFrame]->_tempo || tempo != _lastTempo) {
-		_puppetTempo = 0;
-	} else if (_puppetTempo) {
-		tempo = _puppetTempo;
-	}
-
-	if (tempo) {
-		const bool waitForClickOnly = _vm->getVersion() < 300;
-		const int maxDelay = _vm->getVersion() < 400 ? 120 : 60;
-		if (tempo >= 256 - maxDelay) {
-			// Delay
-			_nextFrameTime = g_system->getMillis() + (256 - tempo) * 1000;
-		} else if (tempo <= 120) {
-			// FPS
-			_currentFrameRate = tempo;
-			_nextFrameTime = g_system->getMillis() + 1000.0 / (float)_currentFrameRate;
-		} else {
-			if (tempo == 128) {
-				_waitForClick = true;
-				_waitForClickCursor = false;
-				renderCursor(_movie->getWindow()->getMousePos());
-			} else if (!waitForClickOnly && tempo == 135) {
-				// Wait for sound channel 1
-				_waitForChannel = 1;
-			} else if (!waitForClickOnly && tempo == 134) {
-				// Wait for sound channel 2
-				_waitForChannel = 2;
-
-			} else if (!waitForClickOnly && tempo >= 136 && tempo <= 135 + _numChannelsDisplayed) {
-				// Wait for a digital video in a channel to finish playing
-				_waitForVideoChannel = tempo - 135;
-			} else {
-				warning("Unhandled tempo instruction: %d", tempo);
-			}
-			_nextFrameTime = g_system->getMillis();
-		}
-	} else {
-		_nextFrameTime = g_system->getMillis() + 1000.0 / (float)_currentFrameRate;
-	}
-	_lastTempo = tempo;
-
-	if (debugChannelSet(-1, kDebugSlow))
-		_nextFrameTime += 1000;
 }
 
 void Score::renderFrame(uint16 frameId, RenderMode mode) {


Commit: 1524ee36152b6b4c71d114a6faca2ade55680611
    https://github.com/scummvm/scummvm/commit/1524ee36152b6b4c71d114a6faca2ade55680611
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Fix coloring of 1-bit bitmaps

If a channel contains a 1-bit bitmap cast member, use the foreground
color instead of black when rendering in Background Transparent mode.

Fixes various text bitmaps in Total Distortion and iD4 Mission Disk 1.

Changed paths:
    engines/director/channel.cpp
    engines/director/director.h
    engines/director/frame.cpp
    engines/director/frame.h
    engines/director/graphics.cpp
    engines/director/score.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 5b214ba5564..81feae54cf6 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -112,6 +112,12 @@ DirectorPlotData Channel::getPlotData() {
 	pd.dst = nullptr;
 
 	pd.srf = getSurface();
+	if (_sprite->_spriteType == kBitmapSprite &&
+		_sprite->_cast && _sprite->_cast->_type == kCastBitmap &&
+		((BitmapCastMember *)_sprite->_cast)->_bitsPerPixel == 1) {
+		// Add override flag for 1-bit images
+		pd.oneBitImage = true;
+	}
 	if (!pd.srf && _sprite->_spriteType != kBitmapSprite) {
 		// Shapes come colourized from macDrawPixel
 		pd.ms = _sprite->getShape();
diff --git a/engines/director/director.h b/engines/director/director.h
index e6ee3f82ec9..7e4b34e6fb7 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -285,24 +285,25 @@ public:
 // An extension of MacPlotData for interfacing with inks and patterns without
 // needing extra surfaces.
 struct DirectorPlotData {
-	DirectorEngine *d;
-	Graphics::ManagedSurface *dst;
+	DirectorEngine *d = nullptr;
+	Graphics::ManagedSurface *dst = nullptr;
 
 	Common::Rect destRect;
 	Common::Point srcPoint;
 
-	Graphics::ManagedSurface *srf;
-	MacShape *ms;
+	Graphics::ManagedSurface *srf = nullptr;
+	MacShape *ms = nullptr;
 
-	SpriteType sprite;
-	InkType ink;
+	SpriteType sprite = kInactiveSprite;
+	bool oneBitImage = false;
+	InkType ink = kInkTypeCopy;
 	uint32 colorWhite;
 	uint32 colorBlack;
-	int alpha;
+	int alpha = 0;
 
 	uint32 backColor;
 	uint32 foreColor;
-	bool applyColor;
+	bool applyColor = false;
 
 	// graphics.cpp
 	void setApplyColor();
@@ -312,12 +313,8 @@ struct DirectorPlotData {
 	void inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
 
 	DirectorPlotData(DirectorEngine *d_, SpriteType s, InkType i, int a, uint32 b, uint32 f) : d(d_), sprite(s), ink(i), alpha(a), backColor(b), foreColor(f) {
-		srf = nullptr;
-		ms = nullptr;
-		dst = nullptr;
 		colorWhite = d->_wm->_colorWhite;
 		colorBlack = d->_wm->_colorBlack;
-		applyColor = false;
 	}
 
 	DirectorPlotData(const DirectorPlotData &old) : d(old.d), sprite(old.sprite),
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 6820450a553..35673c670a7 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -127,7 +127,7 @@ void Frame::readChannel(Common::SeekableReadStreamEndian &stream, uint16 offset,
 	}
 }
 
-void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
+void Frame::readChannels(Common::SeekableReadStreamEndian *stream, uint16 version) {
 	byte unk[24];
 
 	if (version < kFileVer400) {
@@ -181,6 +181,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x %02x %02x %02x", unk[0],
 			unk[1], unk[2], unk[3], unk[4], unk[5]);
 	} else if (version >= kFileVer400 && version < kFileVer500) {
+		if (debugChannelSet(8, kDebugLoading)) {
+			debugC(8, kDebugLoading, "Frame::readChannels(): 40 byte header");
+			stream->hexdump(40);
+		}
 		// Sound/Tempo/Transition
 		int unk1 = stream->readByte();
 		if (unk1) {
@@ -272,6 +276,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
 		Sprite &sprite = *_sprites[i + 1];
 
 		if (version < kFileVer500) {
+			if (debugChannelSet(8, kDebugLoading)) {
+				debugC(8, kDebugLoading, "Frame::readChannels(): channel %d, 22 bytes", i);
+				stream->hexdump(22);
+			}
 			sprite._scriptId = CastMemberID(stream->readByte(), 0);
 			sprite._spriteType = (SpriteType)stream->readByte();
 			sprite._enabled = sprite._spriteType != kInactiveSprite;
@@ -402,7 +410,7 @@ Common::String Frame::formatChannelInfo() {
 	for (int i = 0; i < _numChannels; i++) {
 		Sprite &sprite = *_sprites[i + 1];
 		if (sprite._castId.member) {
-			result += Common::String::format("CH: %-3d castId: %s [inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x\n",
+			result += Common::String::format("CH: %-3d castId: %s, [inkData: 0x%02x [ink: %d, trails: %d, line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d], script: %s, flags2: 0x%x, unk2: 0x%x, unk3: 0x%x\n",
 				i + 1, sprite._castId.asString().c_str(), sprite._inkData,
 				sprite._ink, sprite._trails, sprite._thickness, sprite._width, sprite._height,
 				sprite._startPoint.x, sprite._startPoint.y,
diff --git a/engines/director/frame.h b/engines/director/frame.h
index 27042cdea39..ba4901c3dd6 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -91,7 +91,7 @@ public:
 
 	Score *getScore() const { return _score; }
 
-	void readChannels(Common::ReadStreamEndian *stream, uint16 version);
+	void readChannels(Common::SeekableReadStreamEndian *stream, uint16 version);
 	void readChannel(Common::SeekableReadStreamEndian &stream, uint16 offset, uint16 size);
 
 	void executeImmediateScripts();
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 9cd25276e2a..3f5f93992d1 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -288,7 +288,13 @@ void inkDrawPixel(int x, int y, int src, void *data) {
 
  	switch (p->ink) {
 	case kInkTypeBackgndTrans:
-		*dst = (src == (int)p->backColor) ? *dst : src;
+		if (p->oneBitImage) {
+			// One-bit images have a slightly different rendering algorithm for BackgndTrans.
+			// Foreground colour is used, and background colour is ignored.
+			*dst = (src == (int)p->colorBlack) ? p->foreColor : *dst;
+		} else {
+			*dst = (src == (int)p->backColor) ? *dst : src;
+		}
 		break;
 	case kInkTypeMatte:
 		// fall through
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 7b02d12eadc..85870e30f83 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1398,7 +1398,7 @@ Common::String Score::formatChannelInfo() {
 		Channel &channel = *_channels[i + 1];
 		Sprite &sprite = *channel._sprite;
 		if (sprite._castId.member) {
-			result += Common::String::format("CH: %-3d castId: %s, visible:%d,[inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x, constraint: %d, puppet: %d, stretch: %d\n",
+			result += Common::String::format("CH: %-3d castId: %s, visible: %d, [inkData: 0x%02x [ink: %d, trails: %d, line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d], script: %s, flags2: 0x%x, unk2: 0x%x, unk3: 0x%x, constraint: %d, puppet: %d, stretch: %d\n",
 				i + 1, sprite._castId.asString().c_str(), channel._visible, sprite._inkData,
 				sprite._ink, sprite._trails, sprite._thickness, channel._width, channel._height,
 				channel._currentPoint.x, channel._currentPoint.y,


Commit: 665a76536e604fb1c5777eb0cf7ca44b575c7aa1
    https://github.com/scummvm/scummvm/commit/665a76536e604fb1c5777eb0cf7ca44b575c7aa1
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Fix setter for "the rect of sprite"

Normally you can only change the width and height of a sprite when the
sprite is a puppet, and the stretch flag is set. Apparently for shapes,
all that's required is the puppet flag.

Fixes the mouse cursor bounding box in DEVO Presents: Adventures of the
Smart Patrol.

Changed paths:
    engines/director/channel.cpp
    engines/director/lingo/lingo-the.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 81feae54cf6..3071ae48ef6 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -540,26 +540,35 @@ void Channel::replaceSprite(Sprite *nextSprite) {
 }
 
 void Channel::setWidth(int w) {
-	if (_sprite->_puppet && _sprite->_stretch) {
+	if (_sprite->_puppet) {
+		if (!(_sprite->_cast && _sprite->_cast->_type == kCastShape) && !_sprite->_stretch)
+			return;
 		_width = MAX<int>(w, 0);
 	}
 }
 
 void Channel::setHeight(int h) {
-	if (_sprite->_puppet && _sprite->_stretch) {
+	if (_sprite->_puppet) {
+		if (!(_sprite->_cast && _sprite->_cast->_type == kCastShape) && !_sprite->_stretch)
+			return;
 		_height = MAX<int>(h, 0);
 	}
 }
 
 void Channel::setBbox(int l, int t, int r, int b) {
-	if (_sprite->_puppet && _sprite->_stretch) {
+	if (_sprite->_puppet) {
+		if (!(_sprite->_cast && _sprite->_cast->_type == kCastShape) && !_sprite->_stretch)
+			return;
 		_width = r - l;
 		_height = b - t;
 
-		_currentPoint.x = l;
-		_currentPoint.y = t;
+		_currentPoint.x = (int16)((l + r) / 2);
+		_currentPoint.y = (int16)((t + b) / 2);
 
 		addRegistrationOffset(_currentPoint, true);
+
+		_currentPoint.x -= (int16)((_sprite->_width) / 2);
+		_currentPoint.y -= (int16)((_sprite->_height) / 2);
 	}
 }
 
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 6f0e4057c1c..a81de6f21be 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1576,9 +1576,10 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 	case kTheRect:
 		if (d.type == RECT || (d.type == ARRAY && d.u.farr->arr.size() >= 4)) {
 			score->renderSprites(score->getCurrentFrame(), kRenderForceUpdate);
-			channel->_currentPoint = Common::Point(d.u.farr->arr[0].u.i, d.u.farr->arr[1].u.i);
-			sprite->_width = d.u.farr->arr[2].u.i - d.u.farr->arr[0].u.i;
-			sprite->_height = d.u.farr->arr[3].u.i - d.u.farr->arr[1].u.i;
+			channel->setBbox(
+				d.u.farr->arr[0].u.i, d.u.farr->arr[1].u.i,
+				d.u.farr->arr[2].u.i, d.u.farr->arr[3].u.i
+			);
 			channel->_dirty = true;
 		}
 		break;


Commit: 93262a99fbedce65cba488409c38554a900b84e5
    https://github.com/scummvm/scummvm/commit/93262a99fbedce65cba488409c38554a900b84e5
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Add memory guardrails for inkBlitSurface

Changed paths:
    engines/director/graphics.cpp


diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 3f5f93992d1..b65baa0a11d 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -571,6 +571,9 @@ void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Sur
 	if (sprite == kTextSprite)
 		applyColor = false;
 
+	Common::Rect srfClip = srf->getBounds();
+	bool failedBoundsCheck = false;
+
 	srcPoint.y = abs(srcRect.top - destRect.top);
 	for (int i = 0; i < destRect.height(); i++, srcPoint.y++) {
 		if (d->_wm->_pixelformat.bytesPerPixel == 1) {
@@ -578,6 +581,11 @@ void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Sur
 			const byte *msk = mask ? (const byte *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
 
 			for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
+				if (!srfClip.contains(srcPoint)) {
+					failedBoundsCheck = true;
+					continue;
+				}
+
 				if (!mask || (msk && !(*msk++))) {
 					(d->getInkDrawPixel())(destRect.left + j, destRect.top + i,
 											preprocessColor(*((byte *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
@@ -588,6 +596,11 @@ void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Sur
 			const uint32 *msk = mask ? (const uint32 *)mask->getBasePtr(srcPoint.x, srcPoint.y) : nullptr;
 
 			for (int j = 0; j < destRect.width(); j++, srcPoint.x++) {
+				if (!srfClip.contains(srcPoint)) {
+					failedBoundsCheck = true;
+					continue;
+				}
+
 				if (!mask || (msk && !(*msk++))) {
 					(d->getInkDrawPixel())(destRect.left + j, destRect.top + i,
 											preprocessColor(*((uint32 *)srf->getBasePtr(srcPoint.x, srcPoint.y))), this);
@@ -595,6 +608,14 @@ void DirectorPlotData::inkBlitSurface(Common::Rect &srcRect, const Graphics::Sur
 			}
 		}
 	}
+
+	if (failedBoundsCheck) {
+		warning("DirectorPlotData::inkBlitSurface: Out of bounds - srfClip: %d,%d,%d,%d, srcRect: %d,%d,%d,%d, dstRect: %d,%d,%d,%d",
+				srfClip.left, srfClip.top, srfClip.right, srfClip.bottom,
+				srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
+				destRect.left, destRect.top, destRect.right, destRect.bottom);
+	}
+
 }
 
 void DirectorPlotData::inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask) {


Commit: f36205be6710b041ce95cfbd9f20102b54e5bb03
    https://github.com/scummvm/scummvm/commit/f36205be6710b041ce95cfbd9f20102b54e5bb03
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Reduce Lingo warning spam

Changed paths:
    engines/director/lingo/lingo-code.cpp


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index d70e7cf9fda..4d3b401c9a5 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1597,8 +1597,10 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
 
 	if (funcSym.nargs != -1) {
 		if (funcSym.type == HANDLER || funcSym.type == HBLTIN) {
+			// Lingo supports providing a different number of arguments than expected,
+			// and several games rely on this behaviour.
 			if (funcSym.maxArgs < nargs) {
-				warning("Incorrect number of arguments for handler %s (%d, expected %d to %d). Dropping extra %d",
+				debugC(kDebugLingoExec, 1, "Incorrect number of arguments for handler '%s' (%d, expected %d to %d). Dropping extra %d",
 							funcSym.name->c_str(), nargs, funcSym.nargs, funcSym.maxArgs, nargs - funcSym.maxArgs);
 				while (nargs > funcSym.maxArgs) {
 					g_lingo->pop();
@@ -1606,7 +1608,7 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
 				}
 			}
 			if (funcSym.nargs > nargs) {
-				warning("Incorrect number of arguments for handler %s (%d, expected %d to %d). Adding extra %d voids",
+				debugC(kDebugLingoExec, 1, "Incorrect number of arguments for handler '%s' (%d, expected %d to %d). Adding extra %d voids",
 							funcSym.name->c_str(), nargs, funcSym.nargs, funcSym.maxArgs, funcSym.nargs - nargs);
 				while (nargs < funcSym.nargs) {
 					Datum d;
@@ -1617,7 +1619,7 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
 				}
 			}
 		} else if (funcSym.nargs > nargs || funcSym.maxArgs < nargs) {
-			warning("Incorrect number of arguments for builtin %s (%d, expected %d to %d). Dropping %d stack items.",
+			warning("Incorrect number of arguments for builtin '%s' (%d, expected %d to %d). Dropping %d stack items.",
 						funcSym.name->c_str(), nargs, funcSym.nargs, funcSym.maxArgs, nargs);
 
 			for (int i = 0; i < nargs; i++)
@@ -1651,16 +1653,16 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
 		if (funcSym.u.bltin != LB::b_return && funcSym.u.bltin != LB::b_value) {
 			if (stackSize == stackSizeBefore + 1) {
 				if (!allowRetVal) {
-					warning("dropping return value");
-					g_lingo->pop();
+					Datum extra = g_lingo->pop();
+					warning("Builtin '%s' dropping return value: %s", funcSym.name->c_str(), extra.asString(true).c_str());
 				}
 			} else if (stackSize == stackSizeBefore) {
 				if (allowRetVal)
-					error("builtin function %s did not return value", funcSym.name->c_str());
+					error("Builtin '%s' did not return value", funcSym.name->c_str());
 			} else if (stackSize > stackSizeBefore) {
-				error("builtin %s returned extra %d values", funcSym.name->c_str(), stackSize - stackSizeBefore);
+				error("Builtin '%s' returned extra %d values", funcSym.name->c_str(), stackSize - stackSizeBefore);
 			} else {
-				error("builtin %s popped extra %d values", funcSym.name->c_str(), stackSizeBefore - stackSize);
+				error("Builtin '%s' popped extra %d values", funcSym.name->c_str(), stackSizeBefore - stackSize);
 			}
 		}
 		return;


Commit: d4d40270c233f3b19ee404cc27782991163197d2
    https://github.com/scummvm/scummvm/commit/d4d40270c233f3b19ee404cc27782991163197d2
Author: Scott Percival (code at moral.net.au)
Date: 2022-11-18T16:28:05+01:00

Commit Message:
DIRECTOR: Fix file location for P.A.W.S.

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 46b561dd4bc..8b3c1833470 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -4296,7 +4296,7 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	MACGAME1("paws", "", "Start the Dog!", "af8fad5423f5416fe7743198e3909294", 325061, 404),
 	MACDEMO1("paws", "Making of", "The Making of P.A.W.S", "a55b1e9e9d04a2234189a6bcfbe69e4c", 295404, 404),
-	WINGAME1("paws", "", "STARTDOG.EXE", "5c9a56c88b4bb8732377f93f62a885a4", 818961, 404),
+	WINGAME1("paws", "", "PAWS_HD/STARTDOG.EXE", "5c9a56c88b4bb8732377f93f62a885a4", 818961, 404),
 	WINDEMO1("paws", "Making of", "MAKEPAWS.EXE", "559f4c728a348c18b96cddaf102e3413", 874293, 404),
 
 	WINDEMO1("pbbear", "Sampler", "PBBEAR.EXE", "dc58e6e06807f4a4a4cc278f8748659f", 696807, 404),




More information about the Scummvm-git-logs mailing list