[Scummvm-git-logs] scummvm master -> 889130a3faf2a2b28471567ad5ac3563dd913ad0

sev- noreply at scummvm.org
Sun Jul 16 12:01:52 UTC 2023


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

Summary:
50b88f8622 DIRECTOR: Add FPS quirk for Wrath of the Gods
f4bab7a34d DIRECTOR: Add missing guardrail for Cast::loadExternalSound
889130a3fa DIRECTOR: Share Sprite parsing code between Frame and FilmLoopCastMember


Commit: 50b88f8622cf750d1d7d2a9759dea4ae284d9b77
    https://github.com/scummvm/scummvm/commit/50b88f8622cf750d1d7d2a9759dea4ae284d9b77
Author: Scott Percival (code at moral.net.au)
Date: 2023-07-16T14:01:48+02:00

Commit Message:
DIRECTOR: Add FPS quirk for Wrath of the Gods

Changed paths:
    engines/director/game-quirks.cpp


diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 37010dee347..7ee7a7ebcbb 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -163,6 +163,11 @@ struct Quirk {
 	{ "easternmind", Common::kPlatformMacintosh, &quirkLimit15FPS },
 	{ "easternmind", Common::kPlatformWindows, &quirkLimit15FPS },
 
+	// Wrath of the Gods has shooting gallery minigames which are
+	// clocked to 60fps; in reality this is far too fast to be playable.
+	{ "wrath", Common::kPlatformMacintosh, &quirkLimit15FPS },
+	{ "wrath", Common::kPlatformWindows, &quirkLimit15FPS },
+
 	// Rodem expects to be able to track the mouse cursor outside the
 	// window, which is impossible in ScummVM. Giving it a virtual
 	// desktop allows it to work like it would have on the original OS.


Commit: f4bab7a34d2581f9627b3b20b9fd588361b50a1a
    https://github.com/scummvm/scummvm/commit/f4bab7a34d2581f9627b3b20b9fd588361b50a1a
Author: Scott Percival (code at moral.net.au)
Date: 2023-07-16T14:01:48+02:00

Commit Message:
DIRECTOR: Add missing guardrail for Cast::loadExternalSound

Changed paths:
    engines/director/cast.cpp


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 3e6bfa2f027..f7ae21bead6 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -818,6 +818,11 @@ void Cast::loadExternalSound(Common::SeekableReadStreamEndian &stream) {
 
 	Common::Path resPath = findPath(str, true, true, false);
 
+	if (resPath.empty()) {
+		warning("Cast::loadExternalSound: could not find external sound file %s", str.c_str());
+		return;
+	}
+
 	g_director->openArchive(resPath);
 }
 


Commit: 889130a3faf2a2b28471567ad5ac3563dd913ad0
    https://github.com/scummvm/scummvm/commit/889130a3faf2a2b28471567ad5ac3563dd913ad0
Author: Scott Percival (code at moral.net.au)
Date: 2023-07-16T14:01:48+02:00

Commit Message:
DIRECTOR: Share Sprite parsing code between Frame and FilmLoopCastMember

Changed paths:
    engines/director/castmember/filmloop.cpp
    engines/director/castmember/filmloop.h
    engines/director/frame.cpp
    engines/director/frame.h
    engines/director/score.cpp
    engines/director/sprite.h


diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index add4897f098..860a9479c9f 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -29,6 +29,7 @@
 #include "director/director.h"
 #include "director/cast.h"
 #include "director/channel.h"
+#include "director/frame.h"
 #include "director/movie.h"
 #include "director/window.h"
 #include "director/castmember/bitmap.h"
@@ -111,25 +112,25 @@ Common::Array<Channel> *FilmLoopCastMember::getSubChannels(Common::Rect &bbox, C
 	return &_subchannels;
 }
 
-void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stream) {
+void FilmLoopCastMember::loadFilmLoopDataD2(Common::SeekableReadStreamEndian &stream) {
 	_initialRect = Common::Rect();
 	_frames.clear();
 
 	uint32 size = stream.readUint32BE();
 	if (debugChannelSet(5, kDebugLoading)) {
-		debugC(5, kDebugLoading, "loadFilmLoopData: SCVW body:");
+		debugC(5, kDebugLoading, "loadFilmLoopDataD2: SCVW body:");
 		uint32 pos = stream.pos();
 		stream.seek(0);
 		stream.hexdump(size);
 		stream.seek(pos);
 	}
-	uint16 channelSize = 16;
+	uint16 channelSize = kSprChannelSizeD2;
 	FilmLoopFrame newFrame;
 
 	while (stream.pos() < size) {
 		uint16 frameSize = stream.readUint16BE() - 2;
 		if (debugChannelSet(5, kDebugLoading)) {
-			debugC(5, kDebugLoading, "loadFilmLoopData: Frame entry:");
+			debugC(5, kDebugLoading, "loadFilmLoopDataD2: Frame entry:");
 			stream.hexdump(frameSize);
 		}
 
@@ -137,87 +138,49 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
 			int msgWidth = stream.readByte() * 2;
 			int order = stream.readByte() * 2 - 0x20;
 			frameSize -= 2;
-			debugC(8, kDebugLoading, "loadFilmLoopData: Message: msgWidth %d, order %d", msgWidth, order);
+
+			int channel = (order / channelSize) - 1;
+			int channelOffset = order % channelSize;
+
+			debugC(8, kDebugLoading, "loadFilmLoopDataD2: Message: msgWidth %d, channel %d, channelOffset %d", msgWidth, channel, channelOffset);
 			if (debugChannelSet(8, kDebugLoading)) {
 				stream.hexdump(msgWidth);
 			}
 
-			int fieldPosition = order;
-			int finishPosition = order + msgWidth;
-			while (fieldPosition < finishPosition) {
-				int channel = (fieldPosition / channelSize);
-				int channelOffset = fieldPosition % channelSize;
+			uint16 segSize = msgWidth;
+			uint16 nextStart = (channel + 1) * kSprChannelSizeD2;
 
+			while (segSize > 0) {
 				Sprite sprite(nullptr);
 				sprite._movie = g_director->getCurrentMovie();
 				if (newFrame.sprites.contains(channel)) {
 					sprite = newFrame.sprites.getVal(channel);
 				}
+
 				sprite._spriteType = kCastMemberSprite;
 				sprite._puppet = 1;
 				sprite._stretch = 1;
 
-				switch (channelOffset) {
-				case kSpritePositionUnk1:
-					stream.readByte();
-					fieldPosition++;
-					break;
-				case kSpritePositionEnabled:
-					sprite._enabled = stream.readByte() != 0;
-					fieldPosition++;
-					break;
-				case kSpritePositionUnk2:
-					stream.readUint16BE();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionFlags:
-					sprite._thickness = stream.readByte();
-					sprite._inkData = stream.readByte();
-					sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
-
-					if (sprite._inkData & 0x40)
-						sprite._trails = 1;
-					else
-						sprite._trails = 0;
-
-					fieldPosition += 2;
-					break;
-				case kSpritePositionCastId:
-					sprite.setCast(CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB));
-					fieldPosition += 2;
-					break;
-				case kSpritePositionY:
-					sprite._startPoint.y = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionX:
-					sprite._startPoint.x = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionWidth:
-					sprite._width = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionHeight:
-					sprite._height = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				default:
-					stream.readUint16BE();
-					fieldPosition += 2;
-					break;
-				}
+				uint16 needSize = MIN((uint16)(nextStart - channelOffset), segSize);
+				int startPosition = stream.pos() - channelOffset;
+				int finishPosition = stream.pos() + needSize;
+				readSpriteDataD2(stream, sprite, startPosition, finishPosition);
 				newFrame.sprites.setVal(channel, sprite);
+				segSize -= needSize;
+				channel += 1;
+				channelOffset = 0;
+				nextStart += kSprChannelSizeD2;
 			}
 
 			frameSize -= msgWidth;
 		}
 
 		for (auto &s : newFrame.sprites) {
-			debugC(5, kDebugLoading, "loadFilmLoopData: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
+			debugC(5, kDebugLoading, "loadFilmLoopDataD2: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
 					s._value._castId.asString().c_str(), s._value._startPoint.x, s._value._startPoint.y,
 					s._value._width, s._value._height);
 
+			s._value.setCast(s._value._castId);
 			Common::Point topLeft = s._value._startPoint;
 			if (s._value._cast) {
 				topLeft -= s._value._cast->getRegistrationOffset(s._value._width, s._value._height);
@@ -235,23 +198,23 @@ void FilmLoopCastMember::loadFilmLoopData(Common::SeekableReadStreamEndian &stre
 					_initialRect.extend(spriteBbox);
 				}
 			}
-			debugC(8, kDebugLoading, "loadFilmLoopData: New bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
+			debugC(8, kDebugLoading, "loadFilmLoopDataD2: New bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
 
 		}
 
 		_frames.push_back(newFrame);
 
 	}
-	debugC(5, kDebugLoading, "loadFilmLoopData: Full bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
+	debugC(5, kDebugLoading, "loadFilmLoopDataD2: Full bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
 }
 
-void FilmLoopCastMember::loadFilmLoopDataV4(Common::SeekableReadStreamEndian &stream) {
+void FilmLoopCastMember::loadFilmLoopDataD4(Common::SeekableReadStreamEndian &stream) {
 	_initialRect = Common::Rect();
 	_frames.clear();
 
 	uint32 size = stream.readUint32BE();
 	if (debugChannelSet(5, kDebugLoading)) {
-		debugC(5, kDebugLoading, "loadFilmLoopDataV4: SCVW body:");
+		debugC(5, kDebugLoading, "loadFilmLoopDataD4: SCVW body:");
 		uint32 pos = stream.pos();
 		stream.seek(0);
 		stream.hexdump(size);
@@ -259,11 +222,12 @@ void FilmLoopCastMember::loadFilmLoopDataV4(Common::SeekableReadStreamEndian &st
 	}
 	uint32 framesOffset = stream.readUint32BE();
 	if (debugChannelSet(5, kDebugLoading)) {
-		debugC(5, kDebugLoading, "loadFilmLoopDataV4: SCVW header:");
+		debugC(5, kDebugLoading, "loadFilmLoopDataD4: SCVW header:");
 		stream.hexdump(framesOffset - 8);
 	}
 	stream.skip(6);
-	uint16 channelSize = stream.readUint16BE(); // should be 20!
+	uint16 channelSize = kSprChannelSizeD4;
+	stream.readUint16BE(); // should be kSprChannelSizeD4 = 20!
 	stream.skip(framesOffset - 16);
 
 	FilmLoopFrame newFrame;
@@ -271,7 +235,7 @@ void FilmLoopCastMember::loadFilmLoopDataV4(Common::SeekableReadStreamEndian &st
 	while (stream.pos() < size) {
 		uint16 frameSize = stream.readUint16BE() - 2;
 		if (debugChannelSet(5, kDebugLoading)) {
-			debugC(5, kDebugLoading, "loadFilmLoopDataV4: Frame entry:");
+			debugC(5, kDebugLoading, "loadFilmLoopDataD4: Frame entry:");
 			stream.hexdump(frameSize);
 		}
 
@@ -283,93 +247,54 @@ void FilmLoopCastMember::loadFilmLoopDataV4(Common::SeekableReadStreamEndian &st
 			int channel = (order / channelSize) - 1;
 			int channelOffset = order % channelSize;
 
-			Sprite sprite(nullptr);
-			sprite._movie = g_director->getCurrentMovie();
-			if (newFrame.sprites.contains(channel)) {
-				sprite = newFrame.sprites.getVal(channel);
-			}
-			debugC(8, kDebugLoading, "loadFilmLoopDataV4: Message: msgWidth %d, channel %d, channelOffset %d", msgWidth, channel, channelOffset);
+			debugC(8, kDebugLoading, "loadFilmLoopDataD4: Message: msgWidth %d, channel %d, channelOffset %d", msgWidth, channel, channelOffset);
 			if (debugChannelSet(8, kDebugLoading)) {
 				stream.hexdump(msgWidth);
 			}
-			sprite._puppet = 1;
-			sprite._stretch = 1;
-
-			int fieldPosition = channelOffset;
-			int finishPosition = channelOffset + msgWidth;
-			while (fieldPosition < finishPosition) {
-				switch (fieldPosition) {
-				case kSpritePositionUnk1:
-					stream.readByte();
-					fieldPosition++;
-					break;
-				case kSpritePositionEnabled:
-					sprite._enabled = stream.readByte() != 0;
-					fieldPosition++;
-					break;
-				case kSpritePositionUnk2:
-					stream.readUint16BE();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionFlags:
-					sprite._thickness = stream.readByte();
-					sprite._inkData = stream.readByte();
-					sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
-
-					if (sprite._inkData & 0x40)
-						sprite._trails = 1;
-					else
-						sprite._trails = 0;
-
-					fieldPosition += 2;
-					break;
-				case kSpritePositionCastId:
-					sprite.setCast(CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB));
-					fieldPosition += 2;
-					break;
-				case kSpritePositionY:
-					sprite._startPoint.y = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionX:
-					sprite._startPoint.x = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionWidth:
-					sprite._width = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				case kSpritePositionHeight:
-					sprite._height = stream.readUint16();
-					fieldPosition += 2;
-					break;
-				default:
-					stream.readUint16BE();
-					fieldPosition += 2;
-					break;
+
+			uint16 segSize = msgWidth;
+			uint16 nextStart = (channel + 1) * kSprChannelSizeD4;
+
+			while (segSize > 0) {
+				Sprite sprite(nullptr);
+				sprite._movie = g_director->getCurrentMovie();
+				if (newFrame.sprites.contains(channel)) {
+					sprite = newFrame.sprites.getVal(channel);
 				}
+
+				sprite._puppet = 1;
+				sprite._stretch = 1;
+
+				uint16 needSize = MIN((uint16)(nextStart - channelOffset), segSize);
+				int startPosition = stream.pos() - channelOffset;
+				int finishPosition = stream.pos() + needSize;
+				readSpriteDataD4(stream, sprite, startPosition, finishPosition);
+				newFrame.sprites.setVal(channel, sprite);
+				segSize -= needSize;
+				channel += 1;
+				channelOffset = 0;
+				nextStart += kSprChannelSizeD2;
 			}
 
 			frameSize -= msgWidth;
-
-			newFrame.sprites.setVal(channel, sprite);
 		}
 
 		for (auto &s : newFrame.sprites) {
-			debugC(5, kDebugLoading, "loadFilmLoopDataV4: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
+			debugC(5, kDebugLoading, "loadFilmLoopDataD4: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
 					s._value._castId.asString().c_str(), s._value._startPoint.x, s._value._startPoint.y,
 					s._value._width, s._value._height);
 
 			if (s._key == -1) {
-				debugC(5, kDebugLoading, "loadFilmLoopDataV4: Skipping channel -1");
+				debugC(5, kDebugLoading, "loadFilmLoopDataD4: Skipping channel -1");
 				if (s._value._startPoint.x != 0 || s._value._startPoint.y != 0 || s._value._width != 0 ||
 						 (s._value._height != -256 && s._value._height != 0))
-					warning("BUILDBOT: loadFilmLoopDataV4: Malformed VWSC resource: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
+					warning("BUILDBOT: loadFilmLoopDataD4: Malformed VWSC resource: Sprite: channel %d, castId %s, bbox %d %d %d %d", s._key,
 						s._value._castId.asString().c_str(), s._value._startPoint.x, s._value._startPoint.y,
 						s._value._width, s._value._height);
 				continue;
 			}
 
+			s._value.setCast(s._value._castId);
 			Common::Point topLeft = s._value._startPoint;
 			if (s._value._cast) {
 				topLeft -= s._value._cast->getRegistrationOffset(s._value._width, s._value._height);
@@ -387,14 +312,14 @@ void FilmLoopCastMember::loadFilmLoopDataV4(Common::SeekableReadStreamEndian &st
 					_initialRect.extend(spriteBbox);
 				}
 			}
-			debugC(8, kDebugLoading, "loadFilmLoopDataV4: New bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
+			debugC(8, kDebugLoading, "loadFilmLoopDataD4: New bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
 
 		}
 
 		_frames.push_back(newFrame);
 
 	}
-	debugC(5, kDebugLoading, "loadFilmLoopDataV4: Full bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
+	debugC(5, kDebugLoading, "loadFilmLoopDataD4: Full bounding box: %d %d %d %d", _initialRect.left, _initialRect.top, _initialRect.width(), _initialRect.height());
 
 }
 
@@ -421,7 +346,7 @@ void FilmLoopCastMember::load() {
 		Common::SeekableReadStreamEndian *loop = _cast->getResource(tag, filmLoopId);
 		if (loop) {
 			debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
-			loadFilmLoopData(*loop);
+			loadFilmLoopDataD2(*loop);
 			delete loop;
 		} else {
 			warning("FilmLoopCastMember::load(): Film loop not found");
@@ -433,7 +358,7 @@ void FilmLoopCastMember::load() {
 			Common::SeekableReadStreamEndian *loop = _cast->getResource(tag, filmLoopId);
 			if (loop) {
 				debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
-				loadFilmLoopDataV4(*loop);
+				loadFilmLoopDataD4(*loop);
 				delete loop;
 			} else {
 				warning("FilmLoopCastMember::load(): Film loop not found");
diff --git a/engines/director/castmember/filmloop.h b/engines/director/castmember/filmloop.h
index aa00ca820a4..d78efad226f 100644
--- a/engines/director/castmember/filmloop.h
+++ b/engines/director/castmember/filmloop.h
@@ -42,8 +42,10 @@ public:
 
 	Common::Array<Channel> *getSubChannels(Common::Rect &bbox, Channel *channel);
 
-	void loadFilmLoopData(Common::SeekableReadStreamEndian &stream);
-	void loadFilmLoopDataV4(Common::SeekableReadStreamEndian &stream);
+	void loadFilmLoopDataD2(Common::SeekableReadStreamEndian &stream);
+	void loadFilmLoopDataD4(Common::SeekableReadStreamEndian &stream);
+	void loadFilmLoopDataD5(Common::SeekableReadStreamEndian &stream);
+	void loadFilmLoopDataD6(Common::SeekableReadStreamEndian &stream);
 
 	Common::String formatInfo() override;
 
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index d47d371d322..a90cc8f69fe 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -139,33 +139,34 @@ void Frame::readChannel(Common::MemoryReadStreamEndian &stream, uint16 offset, u
  *
  **************************/
 
-enum {
-	kMainChannelSizeD2 = 32,
-	kSprChannelSizeD2 = 16
-};
-
 void Frame::readChannelD2(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+	if (offset < kMainChannelSizeD2) {
+		uint16 needSize = MIN(size, (uint16)(kMainChannelSizeD2 - offset));
+		readMainChannelsD2(stream, offset, needSize);
+		size -= needSize;
+		offset += needSize;
+	}
+
 	if (offset >= kMainChannelSizeD2) {
-		if (size <= kSprChannelSizeD2)
-			readSpriteD2(stream, offset, size);
-		else {
-			// read > 1 sprites channel
-			while (size > kSprChannelSizeD2) {
-				byte spritePosition = (offset - kMainChannelSizeD2) / kSprChannelSizeD2;
-				uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD2 + kMainChannelSizeD2;
-				uint16 needSize = nextStart - offset;
-				readSpriteD2(stream, offset, needSize);
-				offset += needSize;
-				size -= needSize;
-			}
-			readSpriteD2(stream, offset, size);
+		byte spritePosition = (offset - kMainChannelSizeD2) / kSprChannelSizeD2;
+		uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD2 + kMainChannelSizeD2;
+
+		while (size > 0) {
+			uint16 needSize = MIN((uint16)(nextStart - offset), size);
+			readSpriteD2(stream, offset, needSize);
+			offset += needSize;
+			size -= needSize;
+			nextStart += kSprChannelSizeD2;
 		}
-	} else {
-		readMainChannelsD2(stream, offset, size);
 	}
 }
 
 void Frame::readMainChannelsD2(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+	if (debugChannelSet(8, kDebugLoading)) {
+		debugC(8, kDebugLoading, "Frame::readMainChannelsD2(): %d byte header", size);
+		stream.hexdump(size);
+	}
+
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 	byte unk[6];
@@ -260,8 +261,6 @@ void Frame::readMainChannelsD2(Common::MemoryReadStreamEndian &stream, uint16 of
 			debugC(8, kDebugLoading, "Frame::readMainChannelsD2(): STUB: unk1: %02x %02x %02x %02x %02x %02x", unk[0],
 				unk[1], unk[2], unk[3], unk[4], unk[5]);
 			break;
-		case 32:
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
 			error("Frame::readMainChannelsD2(): Miscomputed field position: %ld", stream.pos() - initPos + offset);
@@ -301,8 +300,22 @@ void Frame::readSpriteD2(Common::MemoryReadStreamEndian &stream, uint16 offset,
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
+	readSpriteDataD2(stream, sprite, initPos - fieldPosition, finishPosition);
+
+	if (stream.pos() > finishPosition) {
+		// This means that the relevant `case` label reads too many bytes and must be split
+		error("Frame::readSpriteD2(): Read %ld extra bytes", stream.pos() - finishPosition);
+	}
+
+	// Sometimes removed sprites leave garbage in the channel
+	// We set it to zero, so then could skip
+	if (sprite._width <= 0 || sprite._height <= 0)
+		sprite._width = sprite._height = 0;
+}
+
+void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition) {
 	while (stream.pos() < finishPosition) {
-		switch (stream.pos() - initPos + fieldPosition) {
+		switch (stream.pos() - startPosition) {
 		case 0:
 			sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
 			break;
@@ -313,11 +326,11 @@ void Frame::readSpriteD2(Common::MemoryReadStreamEndian &stream, uint16 offset,
 			break;
 		case 2:
 			// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
-			sprite._foreColor = _vm->transformColor((128 + stream.readByte()) & 0xff);
+			sprite._foreColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
 			break;
 		case 3:
 			// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
-			sprite._backColor = _vm->transformColor((128 + stream.readByte()) & 0xff);
+			sprite._backColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
 			break;
 		case 4:
 			sprite._thickness = stream.readByte();
@@ -351,26 +364,12 @@ void Frame::readSpriteD2(Common::MemoryReadStreamEndian &stream, uint16 offset,
 		case 14:
 			sprite._width = (int16)stream.readUint16();
 			break;
-		case 16:
-			// end of channel, go to next sprite channel
-			readSpriteD2(stream, spriteStart + kSprChannelSizeD2, finishPosition - stream.pos());
-			fieldPosition = finishPosition;
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
-			error("Frame::readSpriteD2(): Miscomputed field position: %ld", stream.pos() - initPos + fieldPosition);
+			error("readSpriteDataD2(): Miscomputed field position: %ld", stream.pos() - startPosition);
 		}
 	}
 
-	if (stream.pos() > finishPosition) {
-		// This means that the relevant `case` label reads too many bytes and must be split
-		error("Frame::readSpriteD2(): Read %ld extra bytes", stream.pos() - finishPosition);
-	}
-
-	// Sometimes removed sprites leave garbage in the channel
-	// We set it to zero, so then could skip
-	if (sprite._width <= 0 || sprite._height <= 0)
-		sprite._width = sprite._height = 0;
 }
 
 
@@ -380,37 +379,33 @@ void Frame::readSpriteD2(Common::MemoryReadStreamEndian &stream, uint16 offset,
  *
  **************************/
 
-enum {
-	kMainChannelSizeD4 = 40,
-	kSprChannelSizeD4 = 20
-};
-
 void Frame::readChannelD4(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
 	// 40 bytes header
+	if (offset < kMainChannelSizeD4) {
+		uint16 needSize = MIN(size, (uint16)(kMainChannelSizeD4 - offset));
+		readMainChannelsD4(stream, offset, needSize);
+		size -= needSize;
+		offset += needSize;
+	}
+
 	if (offset >= kMainChannelSizeD4) {
-		if (size <= kSprChannelSizeD4)
-			readSpriteD4(stream, offset, size);
-		else {
-			// read > 1 sprites channel
-			while (size > kSprChannelSizeD4) {
-				byte spritePosition = (offset - kMainChannelSizeD4) / kSprChannelSizeD4;
-				uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD4 + kMainChannelSizeD4;
-				uint16 needSize = nextStart - offset;
-				readSpriteD4(stream, offset, needSize);
-				offset += needSize;
-				size -= needSize;
-			}
-			readSpriteD4(stream, offset, size);
+		byte spritePosition = (offset - kMainChannelSizeD4) / kSprChannelSizeD4;
+		uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD4 + kMainChannelSizeD4;
+
+		while (size > 0) {
+			uint16 needSize = MIN((uint16)(nextStart - offset), size);
+			readSpriteD4(stream, offset, needSize);
+			offset += needSize;
+			size -= needSize;
+			nextStart += kSprChannelSizeD4;
 		}
-	} else {
-		readMainChannelsD4(stream, offset, size);
 	}
 }
 
 void Frame::readMainChannelsD4(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
 	if (debugChannelSet(8, kDebugLoading)) {
-		debugC(8, kDebugLoading, "Frame::readMainChannelsD4(): 40 byte header");
-		stream.hexdump(kMainChannelSizeD4);
+		debugC(8, kDebugLoading, "Frame::readMainChannelsD4(): %d byte header", size);
+		stream.hexdump(size);
 	}
 
 	uint32 initPos = stream.pos();
@@ -541,8 +536,6 @@ void Frame::readMainChannelsD4(Common::MemoryReadStreamEndian &stream, uint16 of
 			if (unk1)
 				warning("Frame::readMainChannelsD4(): STUB: unk5: 0x%02x", unk1);
 			break;
-		case 40:
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
 			error("Frame::readMainChannelsD4(): Miscomputed field position: %ld", stream.pos() - initPos + offset);
@@ -582,8 +575,22 @@ void Frame::readSpriteD4(Common::MemoryReadStreamEndian &stream, uint16 offset,
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
+	readSpriteDataD4(stream, sprite, initPos - fieldPosition, finishPosition);
+
+	if (stream.pos() > finishPosition) {
+		// This means that the relevant `case` label reads too many bytes and must be split
+		error("Frame::readSpriteD4(): Read %ld extra bytes", stream.pos() - finishPosition);
+	}
+
+	// Sometimes removed sprites leave garbage in the channel
+	// We set it to zero, so then could skip
+	if (sprite._width <= 0 || sprite._height <= 0)
+		sprite._width = sprite._height = 0;
+}
+
+void readSpriteDataD4(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition) {
 	while (stream.pos() < finishPosition) {
-		switch (stream.pos() - initPos + fieldPosition) {
+		switch (stream.pos() - startPosition) {
 		case 0:
 			sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
 			break;
@@ -593,10 +600,10 @@ void Frame::readSpriteD4(Common::MemoryReadStreamEndian &stream, uint16 offset,
 			sprite._enabled = sprite._spriteType != kInactiveSprite;
 			break;
 		case 2:
-			sprite._foreColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 3:
-			sprite._backColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._backColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 4:
 			sprite._thickness = stream.readByte();
@@ -648,26 +655,11 @@ void Frame::readSpriteD4(Common::MemoryReadStreamEndian &stream, uint16 offset,
 		case 19:
 			sprite._blendAmount = stream.readByte();
 			break;
-		case 20:
-			// end of channel, go to next sprite channel
-			readSpriteD4(stream, spriteStart + kSprChannelSizeD4, finishPosition - stream.pos());
-			fieldPosition = finishPosition;
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
-			error("Frame::readSpriteD4(): Miscomputed field position: %ld", stream.pos() - initPos + fieldPosition);
+			error("readSpriteDataD4(): Miscomputed field position: %ld", stream.pos() - startPosition);
 		}
 	}
-
-	if (stream.pos() > finishPosition) {
-		// This means that the relevant `case` label reads too many bytes and must be split
-		error("Frame::readMainChannelsD4(): Read %ld extra bytes", stream.pos() - finishPosition);
-	}
-
-	// Sometimes removed sprites leave garbage in the channel
-	// We set it to zero, so then could skip
-	if (sprite._width <= 0 || sprite._height <= 0)
-		sprite._width = sprite._height = 0;
 }
 
 /**************************
@@ -676,37 +668,33 @@ void Frame::readSpriteD4(Common::MemoryReadStreamEndian &stream, uint16 offset,
  *
  **************************/
 
-enum {
-	kMainChannelSizeD5 = 48,
-	kSprChannelSizeD5 = 24
-};
-
 void Frame::readChannelD5(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
 	// 48 bytes header
+	if (offset < kMainChannelSizeD5) {
+		uint16 needSize = MIN(size, (uint16)(kMainChannelSizeD5 - offset));
+		readMainChannelsD5(stream, offset, needSize);
+		size -= needSize;
+		offset += needSize;
+	}
+
 	if (offset >= kMainChannelSizeD5) {
-		if (size <= kSprChannelSizeD5)
-			readSpriteD5(stream, offset, size);
-		else {
-			// read > 1 sprites channel
-			while (size > kSprChannelSizeD5) {
-				byte spritePosition = (offset - kMainChannelSizeD5) / kSprChannelSizeD5;
-				uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD5 + kMainChannelSizeD5;
-				uint16 needSize = nextStart - offset;
-				readSpriteD5(stream, offset, needSize);
-				offset += needSize;
-				size -= needSize;
-			}
-			readSpriteD5(stream, offset, size);
+		byte spritePosition = (offset - kMainChannelSizeD5) / kSprChannelSizeD5;
+		uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD5 + kMainChannelSizeD5;
+
+		while (size > 0) {
+			uint16 needSize = MIN((uint16)(nextStart - offset), size);
+			readSpriteD5(stream, offset, needSize);
+			offset += needSize;
+			size -= needSize;
+			nextStart += kSprChannelSizeD5;
 		}
-	} else {
-		readMainChannelsD5(stream, offset, size);
 	}
 }
 
 void Frame::readMainChannelsD5(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
 	if (debugChannelSet(8, kDebugLoading)) {
-		debugC(8, kDebugLoading, "Frame::readMainChannelsD5(): 40 byte header");
-		stream.hexdump(kMainChannelSizeD4);
+		debugC(8, kDebugLoading, "Frame::readMainChannelsD5(): %d byte header", size);
+		stream.hexdump(size);
 	}
 
 	uint32 initPos = stream.pos();
@@ -806,8 +794,6 @@ void Frame::readMainChannelsD5(Common::MemoryReadStreamEndian &stream, uint16 of
 				warning("Frame::readMainChannelsD5(): STUB: unk4: %s", s.c_str());
 			}
 			break;
-		case 48:
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
 			error("Frame::readMainChannelsD5(): Miscomputed field position: %ld", stream.pos() - initPos + offset);
@@ -817,7 +803,7 @@ void Frame::readMainChannelsD5(Common::MemoryReadStreamEndian &stream, uint16 of
 
 	if (stream.pos() > finishPosition) {
 		// This means that the relevant `case` label reads too many bytes and must be split
-		error("Frame::readMainChannelsD4(): Read %ld extra bytes", stream.pos() - finishPosition);
+		error("Frame::readMainChannelsD5(): Read %ld extra bytes", stream.pos() - finishPosition);
 	}
 
 	_transChunkSize = CLIP<byte>(_transChunkSize, 0, 128);
@@ -847,8 +833,22 @@ void Frame::readSpriteD5(Common::MemoryReadStreamEndian &stream, uint16 offset,
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
+	readSpriteDataD5(stream, sprite, initPos - fieldPosition, finishPosition);
+
+	if (fieldPosition > finishPosition) {
+		// This means that the relevant `case` label reads too many bytes and must be split
+		error("Frame::readSpriteD5(): Read %ld extra bytes", stream.pos() - finishPosition);
+	}
+
+	// Sometimes removed sprites leave garbage in the channel
+	// We set it to zero, so then could skip
+	if (sprite._width <= 0 || sprite._height <= 0)
+		sprite._width = sprite._height = 0;
+}
+
+void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition) {
 	while (stream.pos() < finishPosition) {
-		switch (stream.pos() - initPos + fieldPosition) {
+		switch (stream.pos() - startPosition) {
 		case 0:
 			sprite._spriteType = (SpriteType)stream.readByte();
 			break;
@@ -885,10 +885,10 @@ void Frame::readSpriteD5(Common::MemoryReadStreamEndian &stream, uint16 offset,
 			}
 			break;
 		case 10:
-			sprite._foreColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 11:
-			sprite._backColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._backColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 12:
 			sprite._startPoint.y = (int16)stream.readUint16();
@@ -923,26 +923,12 @@ void Frame::readSpriteD5(Common::MemoryReadStreamEndian &stream, uint16 offset,
 		case 23:
 			(void)stream.readByte(); // unused
 			break;
-		case 24:
-			// end of channel, go to next sprite channel
-			readSpriteD5(stream, spriteStart + kSprChannelSizeD5, finishPosition - stream.pos());
-			fieldPosition = finishPosition;
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
-			error("Frame::readSpriteD2(): Miscomputed field position: %ld", stream.pos() - initPos + fieldPosition);
+			error("readSpriteDataD5(): Miscomputed field position: %ld", stream.pos() - startPosition);
 		}
 	}
 
-	if (fieldPosition > finishPosition) {
-		// This means that the relevant `case` label reads too many bytes and must be split
-		error("Frame::readMainChannelsD4(): Read %ld extra bytes", stream.pos() - finishPosition);
-	}
-
-	// Sometimes removed sprites leave garbage in the channel
-	// We set it to zero, so then could skip
-	if (sprite._width <= 0 || sprite._height <= 0)
-		sprite._width = sprite._height = 0;
 }
 
 /**************************
@@ -951,34 +937,34 @@ void Frame::readSpriteD5(Common::MemoryReadStreamEndian &stream, uint16 offset,
  *
  **************************/
 
-enum {
-	kMainChannelSizeD6 = 48,
-	kSprChannelSizeD6 = 24
-};
-
 void Frame::readChannelD6(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
 	// 48 bytes header
+	if (offset < kMainChannelSizeD6) {
+		uint16 needSize = MIN(size, (uint16)(kMainChannelSizeD6 - offset));
+		readMainChannelsD6(stream, offset, needSize);
+		size -= needSize;
+		offset += needSize;
+	}
+
 	if (offset >= kMainChannelSizeD6) {
-		if (size <= kSprChannelSizeD6)
-			readSpriteD6(stream, offset, size);
-		else {
-			// read > 1 sprites channel
-			while (size > kSprChannelSizeD6) {
-				byte spritePosition = (offset - kMainChannelSizeD6) / kSprChannelSizeD6;
-				uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD6 + kMainChannelSizeD6;
-				uint16 needSize = nextStart - offset;
-				readSpriteD6(stream, offset, needSize);
-				offset += needSize;
-				size -= needSize;
-			}
-			readSpriteD6(stream, offset, size);
+		byte spritePosition = (offset - kMainChannelSizeD6) / kSprChannelSizeD6;
+		uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD6 + kMainChannelSizeD6;
+
+		while (size > 0) {
+			uint16 needSize = MIN((uint16)(nextStart - offset), size);
+			readSpriteD6(stream, offset, needSize);
+			offset += needSize;
+			size -= needSize;
+			nextStart += kSprChannelSizeD6;
 		}
-	} else {
-		readMainChannelsD6(stream, offset, size);
 	}
 }
 
 void Frame::readMainChannelsD6(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+	if (debugChannelSet(8, kDebugLoading)) {
+		debugC(8, kDebugLoading, "Frame::readMainChannelsD6(): %d byte header", size);
+		stream.hexdump(size);
+	}
 	error("Frame::readMainChannelsD6(): Miscomputed field position: %d", offset);
 }
 
@@ -1005,8 +991,22 @@ void Frame::readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset,
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
+	readSpriteDataD6(stream, sprite, initPos - fieldPosition, finishPosition);
+
+	if (stream.pos() > finishPosition) {
+		// This means that the relevant `case` label reads too many bytes and must be split
+		error("Frame::readSpriteD6(): Read %ld extra bytes", stream.pos() - finishPosition);
+	}
+
+	// Sometimes removed sprites leave garbage in the channel
+	// We set it to zero, so then could skip
+	if (sprite._width <= 0 || sprite._height <= 0)
+		sprite._width = sprite._height = 0;
+}
+
+void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition) {
 	while (stream.pos() < finishPosition) {
-		switch (stream.pos() - initPos + fieldPosition) {
+		switch (stream.pos() - startPosition) {
 		case 0:
 			sprite._spriteType = (SpriteType)stream.readByte();
 			break;
@@ -1021,10 +1021,10 @@ void Frame::readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset,
 
 			break;
 		case 2:
-			sprite._foreColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 3:
-			sprite._backColor = _vm->transformColor((uint8)stream.readByte());
+			sprite._backColor = g_director->transformColor((uint8)stream.readByte());
 			break;
 		case 4: {
 				uint16 castLib = stream.readUint16();
@@ -1071,26 +1071,11 @@ void Frame::readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset,
 		case 23:
 			(void)stream.readByte(); // unused
 			break;
-		case 24:
-			// end of channel, go to next sprite channel
-			readSpriteD6(stream, spriteStart + kSprChannelSizeD6, finishPosition - stream.pos());
-			fieldPosition = finishPosition;
-			break;
 		default:
 			// This means that a `case` label has to be split at this position
-			error("Frame::readSpriteD2(): Miscomputed field position: %ld", stream.pos() - initPos + fieldPosition);
+			error("readSpriteDataD6(): Miscomputed field position: %ld", stream.pos() - startPosition);
 		}
 	}
-
-	if (stream.pos() > finishPosition) {
-		// This means that the relevant `case` label reads too many bytes and must be split
-		error("Frame::readMainChannelsD4(): Read %ld extra bytes", stream.pos() - finishPosition);
-	}
-
-	// Sometimes removed sprites leave garbage in the channel
-	// We set it to zero, so then could skip
-	if (sprite._width <= 0 || sprite._height <= 0)
-		sprite._width = sprite._height = 0;
 }
 
 Common::String Frame::formatChannelInfo() {
diff --git a/engines/director/frame.h b/engines/director/frame.h
index 438be023bdb..4d78b6c96cf 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -43,7 +43,15 @@ class Sprite;
 class TextCastMember;
 
 enum {
-	kChannelDataSize = (25 * 50)
+	kChannelDataSize = (25 * 50),
+	kMainChannelSizeD2 = 32,
+	kSprChannelSizeD2 = 16,
+	kMainChannelSizeD4 = 40,
+	kSprChannelSizeD4 = 20,
+	kMainChannelSizeD5 = 48,
+	kSprChannelSizeD5 = 24,
+	kMainChannelSizeD6 = 48,
+	kSprChannelSizeD6 = 24
 };
 
 struct PaletteInfo {
@@ -154,6 +162,11 @@ public:
 	DirectorEngine *_vm;
 };
 
+void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition);
+void readSpriteDataD4(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition);
+void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition);
+void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition);
+
 } // End of namespace Director
 
 #endif
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index b52176a23b3..2e02ffdf143 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1398,8 +1398,8 @@ void Score::loadFrames(Common::SeekableReadStreamEndian &stream, uint16 version)
 			_framesStream->readUint16(); // Skip
 		}
 
-		warning("STUB: Score::loadFrames. frame1Offset: %x numFrames: %x version: %x spriteRecordSize: %x numChannels: %x numChannelsDisplayed: %x",
-			frame1Offset, _numFrames, _framesVersion, spriteRecordSize, _numChannels, _numChannelsDisplayed);
+		warning("STUB: Score::loadFrames(): frame1Offset: %x, version: %x, spriteRecordSize: %x, numChannels: %x, numChannelsDisplayed: %x",
+			frame1Offset, _framesVersion, spriteRecordSize, _numChannels, _numChannelsDisplayed);
 		// Unknown, some bytes - constant (refer to contuinity).
 	}
 
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 4ae81cc34b1..d8bd0c36c40 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -29,33 +29,6 @@ class BitmapCastMember;
 class ShapeCastMember;
 class TextCastMember;
 
-enum SpritePosition {
-	kSpritePositionUnk1 = 0,
-	kSpritePositionEnabled = 1,
-	kSpritePositionUnk2 = 2,
-	kSpritePositionFlags = 4,
-	kSpritePositionCastId = 6,
-	kSpritePositionY = 8,
-	kSpritePositionX = 10,
-	kSpritePositionHeight = 12,
-	kSpritePositionWidth = 14
-};
-
-enum MainChannelsPosition {
-	kScriptIdPosition = 0,
-	kSoundType1Position,
-	kTransFlagsPosition,
-	kTransChunkSizePosition,
-	kTempoPosition,
-	kTransTypePosition,
-	kSound1Position,
-	kSkipFrameFlagsPosition = 8,
-	kBlendPosition,
-	kSound2Position,
-	kSound2TypePosition = 11,
-	kPalettePosition = 15
-};
-
 class Sprite {
 public:
 	Sprite(Frame *frame = nullptr);




More information about the Scummvm-git-logs mailing list