[Scummvm-git-logs] scummvm master -> a241f67818728da2dcd29725a3c265c170c505d5
sev-
noreply at scummvm.org
Tue Aug 26 22:04:23 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
a241f67818 DIRECTOR: Added stubs for D6/D7 frame data handling
Commit: a241f67818728da2dcd29725a3c265c170c505d5
https://github.com/scummvm/scummvm/commit/a241f67818728da2dcd29725a3c265c170c505d5
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-08-27T00:03:35+02:00
Commit Message:
DIRECTOR: Added stubs for D6/D7 frame data handling
Changed paths:
engines/director/frame.cpp
engines/director/frame.h
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 4c2de99ab74..bb547a33fe5 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -105,6 +105,8 @@ void Frame::readChannel(Common::MemoryReadStreamEndian &stream, uint16 offset, u
readChannelD5(stream, offset, size);
} else if (version >= kFileVer600 && version < kFileVer700) {
readChannelD6(stream, offset, size);
+ } else if (version >= kFileVer700 && version < kFileVer1100) {
+ readChannelD7(stream, offset, size);
} else {
error("Frame::readChannel(): Unsupported Director version: %d", version);
}
@@ -117,6 +119,12 @@ void Frame::writeMainChannels(Common::SeekableWriteStream *writeStream, uint16 v
writeMainChannelsD4(writeStream);
} else if (version >= kFileVer500 && version < kFileVer600) {
writeMainChannelsD5(writeStream);
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ writeMainChannelsD5(writeStream);
+ } else if (version >= kFileVer600 && version < kFileVer700) {
+ writeMainChannelsD6(writeStream);
+ } else if (version >= kFileVer700 && version < kFileVer1100) {
+ writeMainChannelsD7(writeStream);
} else {
warning("Frame::writeChannel(): Unsupported Director version: %d", version);
}
@@ -1213,6 +1221,10 @@ void Frame::readMainChannelsD6(Common::MemoryReadStreamEndian &stream, uint16 of
error("Frame::readMainChannelsD6(): Miscomputed field position: %d", offset);
}
+void Frame::writeMainChannelsD6(Common::SeekableWriteStream *writeStream) {
+ warning("STUB: Frame::writeMainChannelsD6()");
+}
+
void Frame::readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
uint16 spritePosition = (offset - kMainChannelSizeD6) / kSprChannelSizeD6;
uint16 spriteStart = spritePosition * kSprChannelSizeD6 + kMainChannelSizeD6;
@@ -1385,6 +1397,233 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
}
}
+void writeSpriteDataD6(Common::SeekableWriteStream *writeStream, Sprite &sprite) {
+ warning("STUB: writeSpriteDataD6()");
+}
+
+/**************************
+ *
+ * D7 Loading
+ *
+ **************************/
+
+void Frame::readChannelD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+ // 48 bytes header
+ if (offset < kMainChannelSizeD7) {
+ uint16 needSize = MIN(size, (uint16)(kMainChannelSizeD7 - offset));
+ readMainChannelsD7(stream, offset, needSize);
+ size -= needSize;
+ offset += needSize;
+ }
+
+ if (offset >= kMainChannelSizeD7) {
+ byte spritePosition = (offset - kMainChannelSizeD7) / kSprChannelSizeD7;
+ uint16 nextStart = (spritePosition + 1) * kSprChannelSizeD7 + kMainChannelSizeD7;
+
+ while (size > 0) {
+ uint16 needSize = MIN((uint16)(nextStart - offset), size);
+ readSpriteD7(stream, offset, needSize);
+ offset += needSize;
+ size -= needSize;
+ nextStart += kSprChannelSizeD7;
+ }
+ }
+}
+
+void Frame::readMainChannelsD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+ if (debugChannelSet(8, kDebugLoading)) {
+ debugC(8, kDebugLoading, "Frame::readMainChannelsD7(): %d byte header", size);
+ stream.hexdump(size);
+ }
+ error("Frame::readMainChannelsD7(): Miscomputed field position: %d", offset);
+}
+
+void Frame::writeMainChannelsD7(Common::SeekableWriteStream *writeStream) {
+ warning("STUB: Frame::writeMainChannelsD7()");
+}
+
+void Frame::readSpriteD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size) {
+ uint16 spritePosition = (offset - kMainChannelSizeD7) / kSprChannelSizeD7;
+ uint16 spriteStart = spritePosition * kSprChannelSizeD7 + kMainChannelSizeD7;
+
+ uint16 fieldPosition = offset - spriteStart;
+
+ debugC(5, kDebugLoading, "Frame::readSpriteD7(): sprite: %d offset: %d size: %d, field: %d", spritePosition, offset, size, fieldPosition);
+ if (debugChannelSet(8, kDebugLoading)) {
+ stream.hexdump(size);
+ }
+
+ Sprite &sprite = *_sprites[spritePosition + 1];
+
+ uint32 initPos = stream.pos();
+ uint32 finishPosition = initPos + size;
+
+ readSpriteDataD7(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::readSpriteD7(): Read %" PRId64 " 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 readSpriteDataD7(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition) {
+ while (stream.pos() < finishPosition) {
+ switch (stream.pos() - startPosition) {
+ case 0:
+ if (sprite._puppet) {
+ stream.readByte();
+ } else {
+ sprite._spriteType = (SpriteType)stream.readByte();
+ }
+ break;
+ case 1: {
+ byte inkData = stream.readByte();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPInk))
+ continue;
+
+ sprite._inkData = inkData;
+
+ sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+ sprite._trails = sprite._inkData & 0x40 ? true : false;
+ sprite._stretch = sprite._inkData & 0x80 ? true : false;
+ }
+ break;
+ case 2: {
+ uint8 foreColor = stream.readByte();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPForeColor))
+ continue;
+
+ sprite._foreColor = g_director->transformColor(foreColor);
+ }
+ break;
+ case 3: {
+ uint8 backColor = stream.readByte();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPBackColor))
+ continue;
+
+ sprite._backColor = g_director->transformColor(backColor);
+ }
+ break;
+ case 4:
+ if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
+ stream.readSint16();
+ } else {
+ int castLib = stream.readSint16();
+ sprite._castId = CastMemberID(sprite._castId.member, castLib);
+ }
+ break;
+ case 6:
+ if (sprite._puppet || sprite.getAutoPuppet(kAPCast)) {
+ stream.readUint16();
+ } else {
+ uint16 memberID = stream.readUint16();
+ sprite._castId = CastMemberID(memberID, sprite._castId.castLib); // Inherit castLib from previous frame
+ }
+ break;
+ case 8: {
+ int scriptCastLib = stream.readSint16();
+ sprite._scriptId = CastMemberID(sprite._scriptId.member, scriptCastLib);
+ }
+ break;
+ case 10: {
+ uint16 scriptMemberID = stream.readUint16();
+ sprite._scriptId = CastMemberID(scriptMemberID, sprite._scriptId.castLib); // Inherit castLib from previous frame
+ }
+ break;
+ case 12: {
+ uint16 startPointY = stream.readUint16();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPLocV) || sprite.getAutoPuppet(kAPLoc))
+ continue;
+
+ sprite._startPoint.y = startPointY;
+ break;
+ }
+ case 14: {
+ uint16 startPointX = stream.readUint16();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPLocH) || sprite.getAutoPuppet(kAPLoc))
+ continue;
+
+ sprite._startPoint.x = startPointX;
+ }
+ break;
+ case 16: {
+ uint16 height = stream.readUint16();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPHeight))
+ continue;
+
+ sprite._height = height;
+ }
+ break;
+ case 18: {
+ uint16 width = stream.readUint16();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPWidth))
+ continue;
+
+ sprite._width = width;
+ }
+ break;
+ case 20:
+ // & 0x0f scorecolor
+ // 0x10 forecolor is rgb
+ // 0x20 bgcolor is rgb
+ // 0x40 editable
+ // 0x80 moveable
+ sprite._colorcode = stream.readByte();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPMoveable))
+ continue;
+
+ sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+ sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ break;
+ case 21: {
+ byte blendAmount = stream.readByte();
+
+ if (sprite._puppet || sprite.getAutoPuppet(kAPBlend))
+ continue;
+
+ sprite._blendAmount = blendAmount;
+ }
+ break;
+ case 22:
+ if (sprite._puppet) {
+ stream.readByte();
+ } else {
+ sprite._thickness = stream.readByte();
+ }
+ break;
+ case 23:
+ (void)stream.readByte(); // unused
+ break;
+ default:
+ // This means that a `case` label has to be split at this position
+ error("readSpriteDataD7(): Miscomputed field position: %" PRId64, stream.pos() - startPosition);
+ }
+ }
+}
+
+void writeSpriteDataD7(Common::SeekableWriteStream *writeStream, Sprite &sprite) {
+ warning("STUB: writeSpriteDataD7()");
+}
+
+/**************************
+ *
+ * Utility Functions
+ *
+ **************************/
+
Common::String Frame::formatChannelInfo() {
Common::String result;
result += Common::String::format("TMPO: tempo: %d, skipFrameFlag: %d, blend: %d\n",
diff --git a/engines/director/frame.h b/engines/director/frame.h
index f63b2a6a6fc..e6394919946 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -55,6 +55,9 @@ enum {
kMainChannelSizeD6 = 48,
kSprChannelSizeD6 = 24,
+
+ kMainChannelSizeD7 = 48,
+ kSprChannelSizeD7 = 24,
};
struct PaletteInfo {
@@ -188,6 +191,14 @@ private:
void readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size);
void readMainChannelsD6(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size);
+ void writeMainChannelsD6(Common::SeekableWriteStream *writeStream);
+
+ void readChannelD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size);
+ void readSpriteD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size);
+ void readMainChannelsD7(Common::MemoryReadStreamEndian &stream, uint16 offset, uint16 size);
+
+ void writeMainChannelsD7(Common::SeekableWriteStream *writeStream);
+
Image::ImageDecoder *getImageFrom(uint16 spriteId);
Common::String readTextStream(Common::SeekableReadStreamEndian *textStream, TextCastMember *textCast);
@@ -204,9 +215,12 @@ void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
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);
+void readSpriteDataD7(Common::SeekableReadStreamEndian &stream, Sprite &sprite, uint32 startPosition, uint32 finishPosition);
void writeSpriteDataD4(Common::SeekableWriteStream *writeStream, Sprite &sprite);
void writeSpriteDataD5(Common::SeekableWriteStream *writeStream, Sprite &sprite);
+void writeSpriteDataD6(Common::SeekableWriteStream *writeStream, Sprite &sprite);
+void writeSpriteDataD7(Common::SeekableWriteStream *writeStream, Sprite &sprite);
} // End of namespace Director
More information about the Scummvm-git-logs
mailing list