[Scummvm-git-logs] scummvm master -> 246d7e7532bfd98b08017b9cfd8d9a5001cd3717
dreammaster
noreply at scummvm.org
Sat Oct 10 05:47:33 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:
246d7e7532 MADS: Fix Phantom/Dragonsphere engine lifecycle
Commit: 246d7e7532bfd98b08017b9cfd8d9a5001cd3717
https://github.com/scummvm/scummvm/commit/246d7e7532bfd98b08017b9cfd8d9a5001cd3717
Author: fusefib (fibofuse at gmail.com)
Date: 2026-10-10T16:43:13+11:00
Commit Message:
MADS: Fix Phantom/Dragonsphere engine lifecycle
Fixes #17306
Changed paths:
engines/mads/core/game.cpp
engines/mads/core/kernel.cpp
engines/mads/core/kernel.h
diff --git a/engines/mads/core/game.cpp b/engines/mads/core/game.cpp
index b59a4634bf5..928f51e7aca 100644
--- a/engines/mads/core/game.cpp
+++ b/engines/mads/core/game.cpp
@@ -1546,6 +1546,7 @@ static void game_system_maintenance() {
* Calls, in proper order, all daemon code for this framing round.
*/
static void game_daemon_code() {
+ kernel_animations_begin_daemon();
kernel.trigger_setup_mode = KERNEL_TRIGGER_DAEMON;
game_exec_function(room_daemon_code_pointer);
@@ -1815,8 +1816,11 @@ static void game_main_loop() {
// Update any active graphics sequences
kernel_seq_update_all();
- // Update any active animations
- kernel_process_all_animations();
+ // Phantom and Dragonsphere scripts use daemon-observed frames for holds and handoffs.
+ // Preserve each newly exposed frame until that daemon can observe it.
+ // Otherwise, update any active animations as before.
+ kernel_process_all_animations(g_engine->getGameID() == GType_Phantom ||
+ g_engine->getGameID() == GType_Dragonsphere);
// Special mouse cursor update mode
if (kernel.mouse_cursor_point) {
diff --git a/engines/mads/core/kernel.cpp b/engines/mads/core/kernel.cpp
index 1e602b4d4ff..2c65d57a372 100644
--- a/engines/mads/core/kernel.cpp
+++ b/engines/mads/core/kernel.cpp
@@ -1313,9 +1313,17 @@ void kernel_animation_init() {
kernel_anim[count].anim = NULL;
kernel_anim[count].cycled = false;
kernel_anim[count].repeat = false;
+ kernel_anim[count].awaiting_daemon = false;
}
}
+void kernel_animations_begin_daemon() {
+ // Clear before calling room code, not after: an explicit update from that
+ // code may expose another frame that still needs the next daemon pass.
+ for (int count = 0; count < KERNEL_MAX_ANIMATIONS; ++count)
+ kernel_anim[count].awaiting_daemon = false;
+}
+
int kernel_run_animation(const char *name, int trigger_code) {
int found = -1;
int error_flag = true;
@@ -1395,6 +1403,8 @@ int kernel_run_animation(const char *name, int trigger_code) {
error_flag = false;
kernel_anim[found].last_frame = -1;
+ // A new animation may render its initial frame, including during a fade.
+ kernel_anim[found].awaiting_daemon = false;
done:
if (error_flag) {
@@ -1496,6 +1506,9 @@ void kernel_reset_animation(int handle, int frame) {
kernel_anim[handle].frame = frame;
kernel_anim[handle].image = 0;
kernel_anim[handle].doomed = false;
+ // A script-selected frame is an explicit transition, not an unobserved
+ // automatic advance. Preserve parser releases and cross-actor handoffs.
+ kernel_anim[handle].awaiting_daemon = false;
}
}
@@ -1734,6 +1747,9 @@ static void kernel_process_animation(int handle, int asynchronous) {
kernel_anim[handle].frame++;
if (!asynchronous) {
+ // Screen reconstruction uses the asynchronous path and must not create
+ // or consume a daemon observation for the live animation.
+ kernel_anim[handle].awaiting_daemon = true;
if (kernel_anim[handle].frame == kernel_anim[handle].anim->num_frames) {
if (kernel_anim[handle].trigger_code) {
kernel.trigger = kernel_anim[handle].trigger_code;
@@ -1754,12 +1770,18 @@ done:
;
}
-void kernel_process_all_animations() {
+void kernel_process_all_animations(bool require_daemon) {
int count;
int ok_to_update;
for (count = 0; count < KERNEL_MAX_ANIMATIONS; count++) {
if (kernel_anim[count].anim != NULL) {
+ // Do not cross two automatic frame boundaries without giving the
+ // room its daemon pass. FX may bypass trigger delivery restrictions,
+ // but must not bypass this per-animation observation requirement.
+ if (require_daemon && kernel_anim[count].awaiting_daemon)
+ continue;
+
ok_to_update = (kernel.fx || !kernel.trigger ||
(kernel_anim[count].frame != kernel_anim[count].anim->num_frames - 1));
if (ok_to_update) {
@@ -1841,6 +1863,7 @@ void kernel_abort_animation(int handle) {
}
kernel_anim[handle].doomed = false;
+ kernel_anim[handle].awaiting_daemon = false;
go_ahead_and_frag_the_palette();
}
diff --git a/engines/mads/core/kernel.h b/engines/mads/core/kernel.h
index 391d3c16dac..1308d359ded 100644
--- a/engines/mads/core/kernel.h
+++ b/engines/mads/core/kernel.h
@@ -243,7 +243,7 @@ struct Animation {
int repeat; /* Animation should repeat continuously */
int cycled; /* Animation has cycled back to start */
int sprite_loaded; /* Current sprite loaded (for streamers)*/
- byte *buffer[2]; /* Double buffering pointers (streamers)*/
+ byte *buffer[2]; /* Double buffering pointers (streamers)*/
int buffer_id; /* Double buffering index (streamers)*/
int messages; /* Messages currently active from anim */
int frame; /* Current frame */
@@ -261,6 +261,8 @@ struct Animation {
int dynamic_hotspot; /* Attached dynamic hotspot */
int last_frame; /* Most recent frame viewed */
+
+ bool awaiting_daemon; /* Current frame still needs daemon pass*/
};
@@ -531,7 +533,17 @@ extern void kernel_abort_animation(int handle);
extern void kernel_abort_all_animations();
extern void kernel_doom_all_animations();
extern void kernel_abort_doomed_animations();
-extern void kernel_process_all_animations();
+
+/**
+ * A daemon pass observes frames that were pending before the pass began.
+ */
+extern void kernel_animations_begin_daemon();
+
+/**
+ * Explicit updates (menus and in-daemon handoffs) retain their old behavior.
+ * Phantom/Dragonsphere game loops require daemon observation between automatic steps.
+ */
+extern void kernel_process_all_animations(bool require_daemon = false);
extern void kernel_message_init();
extern int kernel_message_add(char *text, int x, int y, int color,
long time_on_screen, int trigger_code, int flags);
More information about the Scummvm-git-logs
mailing list