[Scummvm-git-logs] scummvm master -> 028c5c6bba1f5305d4100bf225b224d147591e54
sev-
noreply at scummvm.org
Sun Jun 28 20:59:27 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
7acb94791d DIRECTOR: LINGO: Implement sendSprite, sendAllSprites and call
028c5c6bba DIRECTOR: Add quirks for TKKG 5-9 and Oscar Mountain
Commit: 7acb94791d6250e364b4349c3c79778fd1fde331
https://github.com/scummvm/scummvm/commit/7acb94791d6250e364b4349c3c79778fd1fde331
Author: Lariaa (30549703+Lariaa at users.noreply.github.com)
Date: 2026-06-28T22:59:22+02:00
Commit Message:
DIRECTOR: LINGO: Implement sendSprite, sendAllSprites and call
Tested with TKKG 2-5 and Löwenzahn 2-4
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-code.cpp
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index ef0815fbd16..c5936651696 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -123,7 +123,7 @@ static const BuiltinProto builtins[] = {
// Control
{ "abort", LB::b_abort, 0, 0, 400, CBLTIN }, // D4 c
{ "cancelIdleLoad", LB::b_cancelIdleLoad,1,1, 500, CBLTIN }, // D5 c
- { "call", LB::b_call, -1,0, 600, CBLTIN }, // D6 c
+ { "call", LB::b_call, -1,0, 600, HBLTIN }, // D6 c (also usable as function)
{ "callAncestor", LB::b_callAncestor, -1,0, 600, CBLTIN }, // D6 c
{ "continue", LB::b_continue, 0, 0, 200, CBLTIN }, // D2 c
{ "dontPassEvent", LB::b_dontPassEvent,0, 0, 200, CBLTIN }, // D2 c
@@ -146,7 +146,7 @@ static const BuiltinProto builtins[] = {
{ "quit", LB::b_quit, 0, 0, 200, CBLTIN }, // D2 c
{ "restart", LB::b_restart, 0, 0, 200, CBLTIN }, // D2 c
{ "return", LB::b_return, 0, 1, 200, CBLTIN }, // D2 f
- { "send", LB::b_call, -1,0, 400, CBLTIN }, // D4 c, undocumented
+ { "send", LB::b_call, -1,0, 400, HBLTIN }, // D4 c, undocumented (also usable as function)
{ "sendAncestor", LB::b_callAncestor, -1,0, 400, CBLTIN }, // D4 c, undocumented
{ "shutDown", LB::b_shutDown, 0, 0, 200, CBLTIN }, // D2 c
{ "startTimer", LB::b_startTimer, 0, 0, 200, CBLTIN }, // D2 c
@@ -202,8 +202,8 @@ static const BuiltinProto builtins[] = {
{ "puppetTransition",LB::b_puppetTransition,-1,0,200, CBLTIN }, // D2 c
{ "ramNeeded", LB::b_ramNeeded, 2, 2, 300, FBLTIN }, // D3.1 f
{ "rollOver", LB::b_rollOver, 0, 1, 200, FBLTIN }, // D2 f
- { "sendAllSprites", LB::b_sendAllSprites,-1,0,600, CBLTIN }, // D6 c
- { "sendSprite", LB::b_sendSprite, -1,0, 600, CBLTIN }, // D6 c
+ { "sendAllSprites", LB::b_sendAllSprites,-1,0,600, HBLTIN }, // D6 c (also usable as function)
+ { "sendSprite", LB::b_sendSprite, -1,0, 600, HBLTIN }, // D6 c (also usable as function)
{ "spriteBox", LB::b_spriteBox, 5, 5, 200, CBLTIN }, // D2 c
{ "unLoad", LB::b_unLoad, 0, 2, 300, CBLTIN }, // D3.1 c
{ "unLoadCast", LB::b_unLoadCast, 0, 2, 300, CBLTIN }, // D3.1 c
@@ -1938,9 +1938,57 @@ void LB::b_abort(int nargs) {
g_lingo->_abort = true;
}
+// Helper: call a named handler on a single behavior instance with extra args.
+// extraArgs is stored in reverse order (as popped from stack).
+static Datum callBehaviorHandler(Datum &instance, const Common::String &msgName, const Common::Array<Datum> &extraArgs) {
+ Symbol sym = instance.u.obj->getMethod(msgName);
+ if (sym.type == VOIDSYM)
+ return Datum();
+
+ g_lingo->push(instance);
+ for (int j = (int)extraArgs.size() - 1; j >= 0; j--)
+ g_lingo->push(extraArgs[j]);
+
+ int frame = g_lingo->_state->callstack.size();
+ LC::call(sym, 1 + (int)extraArgs.size(), true);
+ g_lingo->execute(frame);
+ return g_lingo->pop();
+}
+
void LB::b_call(int nargs) {
- g_lingo->printSTUBWithArglist("b_call", nargs);
- g_lingo->dropStack(nargs);
+ bool allowRetVal = g_lingo->pop().asInt() != 0;
+ if (nargs < 2) {
+ warning("b_call: expected at least 2 args, got %d", nargs);
+ g_lingo->dropStack(nargs);
+ if (allowRetVal)
+ g_lingo->pushVoid();
+ return;
+ }
+
+ int numExtraArgs = nargs - 2;
+ Common::Array<Datum> extraArgs;
+ for (int i = 0; i < numExtraArgs; i++)
+ extraArgs.push_back(g_lingo->pop());
+
+ Datum script = g_lingo->pop();
+ Datum message = g_lingo->pop();
+ Common::String msgName = message.asString();
+
+ Datum result;
+ if (script.type == OBJECT) {
+ result = callBehaviorHandler(script, msgName, extraArgs);
+ } else if (script.type == ARRAY) {
+ for (uint i = 0; i < script.u.farr->arr.size(); i++) {
+ Datum instance = script.u.farr->arr[i];
+ if (instance.type == OBJECT)
+ result = callBehaviorHandler(instance, msgName, extraArgs);
+ }
+ } else {
+ warning("b_call: expected OBJECT or list for script argument");
+ }
+
+ if (allowRetVal)
+ g_lingo->push(result);
}
void LB::b_callAncestor(int nargs) {
@@ -3444,13 +3492,122 @@ void LB::b_rollOver(int nargs) {
}
void LB::b_sendAllSprites(int nargs) {
- g_lingo->printSTUBWithArglist("b_sendAllSprites", nargs);
- g_lingo->dropStack(nargs);
+ bool allowRetVal = g_lingo->pop().asInt() != 0;
+ if (nargs < 1) {
+ warning("b_sendAllSprites: expected at least 1 arg, got %d", nargs);
+ if (allowRetVal)
+ g_lingo->pushVoid();
+ return;
+ }
+
+ int numExtraArgs = nargs - 1;
+ Common::Array<Datum> extraArgs;
+ for (int i = 0; i < numExtraArgs; i++)
+ extraArgs.push_back(g_lingo->pop());
+
+ Datum message = g_lingo->pop();
+ Common::String msgName = message.asString();
+
+ Datum result;
+ Movie *movie = g_director->getCurrentMovie();
+ Score *score = movie ? movie->getScore() : nullptr;
+ if (score) {
+ score->createScriptInstances(score->getCurrentFrameNum());
+
+ bool anyHandled = false;
+ uint savedSpriteNum = movie->_currentSpriteNum;
+ for (uint ch = 1; ch < score->_channels.size(); ch++) {
+ Channel *channel = score->_channels[ch];
+ if (!channel)
+ continue;
+ for (uint i = 0; i < channel->_scriptInstanceList.size(); i++) {
+ Datum instance = channel->_scriptInstanceList[i];
+ if (instance.type != OBJECT)
+ continue;
+ Symbol sym = instance.u.obj->getMethod(msgName);
+ if (sym.type == VOIDSYM)
+ continue;
+ movie->_currentSpriteNum = ch;
+ result = callBehaviorHandler(instance, msgName, extraArgs);
+ movie->_currentSpriteNum = savedSpriteNum;
+ anyHandled = true;
+ }
+ }
+
+ if (!anyHandled) {
+ Symbol h = g_lingo->getHandler(msgName);
+ if (h.type != VOIDSYM) {
+ for (int j = (int)extraArgs.size() - 1; j >= 0; j--)
+ g_lingo->push(extraArgs[j]);
+ int frame = g_lingo->_state->callstack.size();
+ LC::call(h, numExtraArgs, true);
+ g_lingo->execute(frame);
+ result = g_lingo->pop();
+ }
+ }
+ }
+
+ if (allowRetVal)
+ g_lingo->push(result);
}
void LB::b_sendSprite(int nargs) {
- g_lingo->printSTUBWithArglist("b_sendSprite", nargs);
- g_lingo->dropStack(nargs);
+ bool allowRetVal = g_lingo->pop().asInt() != 0;
+ if (nargs < 2) {
+ warning("b_sendSprite: expected at least 2 args, got %d", nargs);
+ g_lingo->dropStack(nargs);
+ if (allowRetVal)
+ g_lingo->pushVoid();
+ return;
+ }
+
+ int numExtraArgs = nargs - 2;
+ Common::Array<Datum> extraArgs;
+ for (int i = 0; i < numExtraArgs; i++)
+ extraArgs.push_back(g_lingo->pop());
+
+ Datum message = g_lingo->pop();
+ int spriteNum = g_lingo->pop().asInt();
+ Common::String msgName = message.asString();
+
+ Datum result;
+ Movie *movie = g_director->getCurrentMovie();
+ Score *score = movie ? movie->getScore() : nullptr;
+ Channel *channel = score ? score->getChannelById((uint16)spriteNum) : nullptr;
+ if (channel) {
+ if (channel->_scriptInstanceList.empty() && channel->_sprite && !channel->_sprite->_behaviors.empty())
+ score->createScriptInstances(score->getCurrentFrameNum());
+
+ bool handled = false;
+ uint savedSpriteNum = movie->_currentSpriteNum;
+ for (uint i = 0; i < channel->_scriptInstanceList.size(); i++) {
+ Datum instance = channel->_scriptInstanceList[i];
+ if (instance.type != OBJECT)
+ continue;
+ Symbol sym = instance.u.obj->getMethod(msgName);
+ if (sym.type == VOIDSYM)
+ continue;
+ movie->_currentSpriteNum = (uint)spriteNum;
+ result = callBehaviorHandler(instance, msgName, extraArgs);
+ movie->_currentSpriteNum = savedSpriteNum;
+ handled = true;
+ }
+
+ if (!handled) {
+ Symbol h = g_lingo->getHandler(msgName);
+ if (h.type != VOIDSYM) {
+ for (int j = (int)extraArgs.size() - 1; j >= 0; j--)
+ g_lingo->push(extraArgs[j]);
+ int frame = g_lingo->_state->callstack.size();
+ LC::call(h, numExtraArgs, true);
+ g_lingo->execute(frame);
+ result = g_lingo->pop();
+ }
+ }
+ }
+
+ if (allowRetVal)
+ g_lingo->push(result);
}
void LB::b_spriteBox(int nargs) {
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 6d1a422f89c..967390ab122 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1807,6 +1807,14 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
(*funcSym.u.bltin)(nargs);
g_lingo->_state->me = retMe;
} else {
+ // sendSprite/sendAllSprites/call/send can be used both as a command and
+ // as a function (returning the handler's result).
+ if (funcSym.name && (funcSym.name->equalsIgnoreCase("sendSprite") ||
+ funcSym.name->equalsIgnoreCase("sendAllSprites") ||
+ funcSym.name->equalsIgnoreCase("call") ||
+ funcSym.name->equalsIgnoreCase("send")))
+ g_lingo->push(Datum(allowRetVal));
+
(*funcSym.u.bltin)(nargs);
}
Commit: 028c5c6bba1f5305d4100bf225b224d147591e54
https://github.com/scummvm/scummvm/commit/028c5c6bba1f5305d4100bf225b224d147591e54
Author: Lariaa (30549703+Lariaa at users.noreply.github.com)
Date: 2026-06-28T22:59:22+02:00
Commit Message:
DIRECTOR: Add quirks for TKKG 5-9 and Oscar Mountain
Changed paths:
engines/director/game-quirks.cpp
diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 26601391c4e..82308bcdac6 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -123,6 +123,30 @@ struct CachedFile {
"PATH.INI",
(const byte *)"[cd-path]\r\npath=d:\\\r\n", -1
},
+ {"tkkg5", Common::kPlatformWindows,
+ "TKKG_5.ini",
+ (const byte *)"[CD]\r\npath=d\r\n", -1
+ },
+ {"tkkg6", Common::kPlatformWindows,
+ "TKKG_6.ini",
+ (const byte *)"[CD]\r\npath=d\r\n", -1
+ },
+ {"tkkg7", Common::kPlatformWindows,
+ "TKKG_7.ini",
+ (const byte *)"[CDpath]\r\npath=d:\\\r\n", -1
+ },
+ {"tkkg8", Common::kPlatformWindows,
+ "TKKG_8.ini",
+ (const byte *)"[CDpath]\r\npath=d:\\\r\n", -1
+ },
+ {"tkkg9", Common::kPlatformWindows,
+ "TKKG_9.ini",
+ (const byte *)"[CDpath]\r\npath=d:\\\r\n", -1
+ },
+ {"oscar5", Common::kPlatformWindows,
+ "Oscar_Be.ini",
+ (const byte *)"[CDpath]\r\npath=d:\\\r\n", -1
+ },
// Professor Finkle's Times Table Factory has an installer that copies a bunch of empty files,
// which the game gets upset about if they don't exist.
More information about the Scummvm-git-logs
mailing list