Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCUMM: Restore the first frame of Indy's reaction drinking from the Grail #3984

Conversation

dwatteau
Copy link
Contributor

@dwatteau dwatteau commented Jun 12, 2022

Once again, this comes from ATMachine's detailed analysis:
https://web.archive.org/web/20111015233333/http://home.comcast.net/~ervind/ij3misc.html

Context

When you find the real Grail in Indy 3 and drink from it, the original game shows this:

indy3-first-frame-before

It's… OK, but Indy looks a bit old and upset for someone who's just found the Grail, no?

That's because the real first frame of this animation has always been hidden until now:

indy3-first-frame-after

Here's script no. 200 in room 87, which deals with this animation:

Script# 200
[0000] (1A) Var[57] = 0;
[0005] (05) drawObject(899,255,255);
[000C] (2E) delay(120);
[0010] (28) if (!Bit[1504]) {
[0015] (1A)   VAR_TIMER_NEXT = 12;
[001A] (05)   drawObject(899,255,255);
[0021] (80)   breakHere();
[0022] (3C)   stopSound(67);
[0024] (1C)   startSound(53);
[0026] (05)   drawObject(900,255,255);
[002D] (80)   breakHere();
[002E] (05)   drawObject(901,255,255);
[0035] (80)   breakHere();
[0036] (05)   drawObject(902,255,255);
[003D] (80)   breakHere();
[003E] (05)   drawObject(903,255,255);
[0045] (80)   breakHere();
[0046] (05)   drawObject(904,255,255);
[004D] (80)   breakHere();
[004E] (05)   drawObject(905,255,255);
[0055] (80)   breakHere();
[0056] (05)   drawObject(906,255,255);
[005D] (1A)   VAR_TIMER_NEXT = 6;
[0062] (1A)   Local[0] = 1;
[0067] (05)   drawObject(907,255,255);
[006E] (80)   breakHere();
[006F] (05)   drawObject(910,255,255);
[0076] (80)   breakHere();
[0077] (05)   drawObject(908,255,255);
[007E] (80)   breakHere();
[007F] (05)   drawObject(911,255,255);
[0086] (80)   breakHere();
[0087] (05)   drawObject(909,255,255);
[008E] (80)   breakHere();
[008F] (05)   drawObject(912,255,255);
[0096] (80)   breakHere();
[0097] (46)   Local[0]++;
[009A] (44)   unless (Local[0] > 5) goto 0067;
[00A1] (**) }
[00A1] (1A) Var[57] = 1;
[00A6] (A0) stopObjectCode();
END

The big if () is when you pick up the wrong Grail.

Notice that drawObject(899,255,255) appears twice, at the top. That's actually the second frame of animation. The first one is the background image, and then some objects are printed on top of it to make the animation.

The problem is the first drawObject(899,255,255) call: it's unconditional and done immediately, so the background is always hidden by this second frame when the closeup starts. I think it's been done so that this cutscene would always reset to a clean state, with no leftover from a previous death (since it will load again as long as you pick up the wrong Grail).

So this PR tries to look to the first (unconditional) drawObject() call, and replaces it with a full reset of any previous object in this cutscene room (the only objects in this room are the animation frames, anyway). This restores the missing first frame of this animation if you die, and makes Indy happier when he finds the Grail.

How to test

  1. Start any version of Indy3. I only have the VGA PC version at the moment, so EGA, Macintosh and FM-TOWNS tests are very welcome.
  2. Type room 86 in the debugger
  3. Pick up any Grail, and drink from it with the water on the right (choose wisely or choose poorly as you wish!)
  4. If you have the death animation, go to step 2 again once Indy says "Be back in a jiffy!". Doing it twice will test the cutscene reset case, i.e. the animation should properly start from scratch again.

(If you need to know which Grail is the real one, look at Var[253] in the debugger, that should be the number of the real Grail when counting from the left)

…rail

The original game always hides this first frame behind the second one,
probably so that this cutscene never starts with some previous frame
leftovers (since this animation will repeat as long as you pick up the
wrong Grail).

This is a bit unfortunate, especially since it also makes Indy appear
older if he drinks from the real Grail.  So, restore this first frame
and just reset any previously drawn object when starting this animation.
@eriktorbjorn
Copy link
Member

@eriktorbjorn eriktorbjorn commented Jun 12, 2022

It seems to work with the 16-color Mac version.

First frame before patch:

indy3-ega-mac-first-frame-before

First frame after patch:

indy3-ega-mac-first-frame-after

This is what the script looks like, so it's not 100% identical, but close enough apparently.

[0000] (1A) Var[57] = 0;
[0005] (05) drawObject(899,255,255);
[000C] (2E) delay(120);
[0010] (28) if (!Var[94 Bit 0]) {
[0015] (1A)   VAR_TIMER_NEXT = 12;
[001A] (05)   drawObject(899,255,255);
[0021] (80)   breakHere();
[0022] (3C)   stopSound(67);
[0024] (1C)   startSound(53);
[0026] (05)   drawObject(900,255,255);
[002D] (80)   breakHere();
[002E] (05)   drawObject(901,255,255);
[0035] (80)   breakHere();
[0036] (05)   drawObject(902,255,255);
[003D] (80)   breakHere();
[003E] (05)   drawObject(903,255,255);
[0045] (80)   breakHere();
[0046] (05)   drawObject(904,255,255);
[004D] (80)   breakHere();
[004E] (05)   drawObject(905,255,255);
[0055] (80)   breakHere();
[0056] (05)   drawObject(906,255,255);
[005D] (1A)   VAR_TIMER_NEXT = 6;
[0062] (1A)   Local[0] = 1;
[0067] (05)   drawObject(907,255,255);
[006E] (80)   breakHere();
[006F] (05)   drawObject(910,255,255);
[0076] (80)   breakHere();
[0077] (05)   drawObject(908,255,255);
[007E] (80)   breakHere();
[007F] (05)   drawObject(911,255,255);
[0086] (80)   breakHere();
[0087] (05)   drawObject(909,255,255);
[008E] (80)   breakHere();
[008F] (05)   drawObject(912,255,255);
[0096] (80)   breakHere();
[0097] (46)   Local[0]++;
[009A] (44)   unless (Local[0] > 5) goto 0067;
[00A1] (**) }
[00A1] (1A) Var[57] = 1;
[00A6] (A0) stopObjectCode();

@bluegr
Copy link
Member

@bluegr bluegr commented Jun 15, 2022

Nice, works like a charm!

@bluegr bluegr merged commit 6f8bd66 into scummvm:master Jun 15, 2022
8 checks passed
@dwatteau dwatteau deleted the fix/indy3-restore-first-frame-drinking-grail-closeup branch Jun 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants