[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