[Scummvm-git-logs] scummvm master -> d4bc9033e98c6e7f365530129ac0e67e16606594
sev-
noreply at scummvm.org
Sat Jul 18 21:13:16 UTC 2026
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:
d4bc9033e9 DIRECTOR: Recognize D7 Cursor Asset Xtra cast members
Commit: d4bc9033e98c6e7f365530129ac0e67e16606594
https://github.com/scummvm/scummvm/commit/d4bc9033e98c6e7f365530129ac0e67e16606594
Author: Gianluca Boiano (morf3089 at gmail.com)
Date: 2026-07-18T23:13:12+02:00
Commit Message:
DIRECTOR: Recognize D7 Cursor Asset Xtra cast members
Parses the cursor payload (hotspot, size, frame interval, referenced
bitmap members) and resolves sprite cursors set to such members to the
referenced bitmaps.
Fixes 'Xtra cast members not yet supported' loading GlobalF.cxt in tkkg7
Changed paths:
A engines/director/lingo/xtras-cast/cursorxtra.cpp
A engines/director/lingo/xtras-cast/cursorxtra.h
engines/director/castmember/xtra.cpp
engines/director/cursor.cpp
engines/director/module.mk
diff --git a/engines/director/castmember/xtra.cpp b/engines/director/castmember/xtra.cpp
index d78b3078d78..f714247b6f2 100644
--- a/engines/director/castmember/xtra.cpp
+++ b/engines/director/castmember/xtra.cpp
@@ -28,6 +28,7 @@
#include "director/castmember/xtra.h"
#include "director/castmember/digitalvideo.h"
#include "director/lingo/lingo-the.h"
+#include "director/lingo/xtras-cast/cursorxtra.h"
#include "director/lingo/xtras-cast/textxtra.h"
namespace Director {
@@ -38,6 +39,7 @@ struct XtraCastMemberProto {
};
static const XtraCastMemberProto xtraCastMemberProtos[] = {
+ { "cursor", CursorXtra::createCastMember },
{ "quickTimeMedia", DigitalVideoCastMember::createFromXtra },
{ "text", TextXtra::createCastMember },
{ "font", nullptr },
diff --git a/engines/director/cursor.cpp b/engines/director/cursor.cpp
index 0738a2c35ac..c5db2e741b5 100644
--- a/engines/director/cursor.cpp
+++ b/engines/director/cursor.cpp
@@ -30,6 +30,7 @@
#include "director/castmember/bitmap.h"
#include "director/picture.h"
#include "director/lingo/lingo-code.h"
+#include "director/lingo/xtras-cast/cursorxtra.h"
namespace Director {
@@ -61,6 +62,22 @@ bool Cursor::operator==(const CursorRef &c) {
void Cursor::readFromCast(Datum cursorCasts) {
if (cursorCasts.type != ARRAY || cursorCasts.u.farr->arr.size() < 1) {
+ // D6+: a bare cast member reference is accepted when it names a
+ // Cursor Asset Xtra member, e.g. `sprite.cursor = member "myCursor"`.
+ if (g_director->getVersion() >= 600 && cursorCasts.type != ARRAY) {
+ CursorXtraCastMember *cursorXtra = dynamic_cast<CursorXtraCastMember *>(g_director->getCurrentMovie()->getCastMember(cursorCasts.asMemberID()));
+ CastMemberID imageId, maskId2;
+ if (cursorXtra && cursorXtra->getCursorInfo(imageId, maskId2)) {
+ Datum d;
+ d.type = ARRAY;
+ d.u.farr = new FArray;
+ d.u.farr->arr.push_back(Datum(imageId));
+ if (!maskId2.isNull())
+ d.u.farr->arr.push_back(Datum(maskId2));
+ readFromCast(d);
+ return;
+ }
+ }
warning("Cursor::readFromCast: Needs array of at least 1");
return;
}
@@ -69,6 +86,7 @@ void Cursor::readFromCast(Datum cursorCasts) {
CastMemberID cursorId = cursorCasts.u.farr->arr[0].asMemberID();
CastMember *cursorCast = g_director->getCurrentMovie()->getCastMember(cursorId);
+
if (!cursorCast || cursorCast->_type != kCastBitmap) {
warning("Cursor::readFromCast: No bitmap cast for cursor");
return;
diff --git a/engines/director/lingo/xtras-cast/cursorxtra.cpp b/engines/director/lingo/xtras-cast/cursorxtra.cpp
new file mode 100644
index 00000000000..9d98e7f3bac
--- /dev/null
+++ b/engines/director/lingo/xtras-cast/cursorxtra.cpp
@@ -0,0 +1,114 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/endian.h"
+
+#include "director/director.h"
+#include "director/cast.h"
+#include "director/castmember/xtra.h"
+#include "director/lingo/xtras-cast/cursorxtra.h"
+
+namespace Director {
+
+namespace CursorXtra {
+
+// 56-byte (static) / 168-byte (animated) "cursor" payload observed in
+// TKKG 7 (D7), all BE32; the member/mask pair mirrors the Lingo
+// `cursor [member, mask]` command:
+// 0: payload size 4: unk (1)
+// 8: hotspot x 12: hotspot y
+// 16: cursor size in px 20: frame interval in ms
+// 24: unk (1) 28: cursor bitmap cast member
+// 32: mask bitmap cast member
+// 36: frame count (1, or 8 with per-frame extras following; unparsed)
+// 40: 16-byte per-instance GUID
+bool parseXtraData(const Common::Array<byte> &data, Info &info) {
+ if (data.size() < 40)
+ return false;
+
+ uint32 payloadSize = READ_BE_UINT32(&data[0]);
+ if (payloadSize != data.size())
+ return false;
+
+ info.hotspot.x = READ_BE_INT32(&data[8]);
+ info.hotspot.y = READ_BE_INT32(&data[12]);
+ info.sizePx = READ_BE_UINT32(&data[16]);
+ info.intervalMs = READ_BE_UINT32(&data[20]);
+ info.member = READ_BE_UINT32(&data[28]);
+ info.mask = READ_BE_UINT32(&data[32]);
+ info.frameCount = READ_BE_UINT32(&data[36]);
+
+ if (!info.member || info.member > 0xFFFF || info.mask > 0xFFFF)
+ return false;
+
+ return true;
+}
+
+CastMember *createCastMember(Cast *cast, uint16 castId, XtraCastMember *xtra) {
+ return new CursorXtraCastMember(cast, castId, *xtra);
+}
+
+} // End of namespace CursorXtra
+
+CursorXtraCastMember::CursorXtraCastMember(Cast *cast, uint16 castId, XtraCastMember &source)
+ : CastMember(cast, castId) {
+ _type = kCastXtra;
+
+ _valid = CursorXtra::parseXtraData(source.getXtraData(), _info);
+ if (!_valid)
+ warning("CursorXtraCastMember: failed to parse %d-byte cursor payload for cast member %d",
+ source.getXtraData().size(), castId);
+ else {
+ debugC(3, kDebugLoading, "CursorXtraCastMember: hotspot: %d,%d, size: %dpx, interval: %dms, member: %d, mask: %d, frames: %d",
+ _info.hotspot.x, _info.hotspot.y, _info.sizePx, _info.intervalMs, _info.member, _info.mask, _info.frameCount);
+ if (_info.frameCount > 1)
+ warning("STUB: CursorXtraCastMember: animated cursor with %d frames not yet supported for cast member %d, using the first frame",
+ _info.frameCount, castId);
+ }
+}
+
+CursorXtraCastMember::CursorXtraCastMember(Cast *cast, uint16 castId, CursorXtraCastMember &source)
+ : CastMember(cast, castId) {
+ _type = kCastXtra;
+ _info = source._info;
+ _valid = source._valid;
+ if (cast == source._cast)
+ _children = source._children;
+}
+
+bool CursorXtraCastMember::getCursorInfo(CastMemberID &image, CastMemberID &mask) {
+ if (!_valid)
+ return false;
+
+ uint16 castLib = _cast->_castLibID;
+ image = CastMemberID(_info.member, castLib);
+ mask = _info.mask ? CastMemberID(_info.mask, castLib) : CastMemberID();
+ return true;
+}
+
+Common::String CursorXtraCastMember::formatInfo() {
+ return Common::String::format(
+ "cursor Xtra: hotspot: %d,%d, size: %dpx, interval: %dms, member: %d, mask: %d, frames: %d",
+ _info.hotspot.x, _info.hotspot.y, _info.sizePx, _info.intervalMs,
+ _info.member, _info.mask, _info.frameCount);
+}
+
+} // End of namespace Director
diff --git a/engines/director/lingo/xtras-cast/cursorxtra.h b/engines/director/lingo/xtras-cast/cursorxtra.h
new file mode 100644
index 00000000000..58c97e03edc
--- /dev/null
+++ b/engines/director/lingo/xtras-cast/cursorxtra.h
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XTRAS_CAST_CURSORXTRA_H
+#define DIRECTOR_LINGO_XTRAS_CAST_CURSORXTRA_H
+
+#include "common/array.h"
+#include "common/rect.h"
+
+#include "director/castmember/castmember.h"
+
+namespace Director {
+
+class XtraCastMember;
+
+namespace CursorXtra {
+
+struct Info {
+ Common::Point hotspot;
+ uint32 sizePx = 0;
+ uint32 intervalMs = 0;
+ uint32 member = 0; // cursor bitmap cast member
+ uint32 mask = 0; // mask bitmap cast member
+ uint32 frameCount = 0;
+};
+
+CastMember *createCastMember(Cast *cast, uint16 castId, XtraCastMember *xtra);
+bool parseXtraData(const Common::Array<byte> &data, Info &info);
+
+} // End of namespace CursorXtra
+
+// "Cursor" Asset Xtra cast member (D6+): a custom (possibly animated)
+// cursor built from bitmap cast members.
+class CursorXtraCastMember : public CastMember {
+public:
+ CursorXtraCastMember(Cast *cast, uint16 castId, XtraCastMember &source);
+ CursorXtraCastMember(Cast *cast, uint16 castId, CursorXtraCastMember &source);
+
+ CastMember *duplicate(Cast *cast, uint16 castId) override { return (CastMember *)(new CursorXtraCastMember(cast, castId, *this)); }
+
+ bool getCursorInfo(CastMemberID &image, CastMemberID &mask);
+
+ Common::String formatInfo() override;
+
+ CursorXtra::Info _info;
+ bool _valid = false;
+};
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 7778af7f3b6..f72a349718b 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -189,6 +189,7 @@ MODULE_OBJS = \
lingo/xlibs/x/xsoundxfcn.o \
lingo/xlibs/x/xwin.o \
lingo/xlibs/y/yasix.o \
+ lingo/xtras-cast/cursorxtra.o \
lingo/xtras-cast/textxtra.o \
lingo/xtras/a/audio.o \
lingo/xtras/b/border.o \
More information about the Scummvm-git-logs
mailing list