#285 closed defect (fixed)
FOA: Extro playing incorrectly
Reported by: | SF/trinity78 | Owned by: | fingolfin |
---|---|---|---|
Priority: | normal | Component: | Engine: SCUMM |
Version: | Keywords: | ||
Cc: | Game: | Indiana Jones 4 |
Description
Game: Indiana Jones 4 - German Floppy OS: Windows 2000 Adv. Server SP 2 ScummVM: DailyBuild 2002/5/19
Bug:
Two minor bugs.
In the closing scene (extro) of indiana jones 4 there are to bugs. First, the music stops after a short time (maybe after the first theme) and doesn't go on. Usually (almost) all themes of the game are played until the credits are over. This happens with both, adlib emulation and midi. Second the sky does not fade red, so this sunset looks a little bit weird with a yellow bright sky.
savegame attached.
Ticket imported from: #558245. Ticket imported from: bugs/285.
Attachments (5)
Change History (41)
by , 23 years ago
Attachment: | atlantis.s07 added |
---|
comment:1 by , 23 years ago
comment:2 by , 23 years ago
Logged In: NO
i found the part which should be responible for the missing sunset:
in script_v1.cpp
case 15:
/*
palmanip? */
a = getVarOrDirectByte(0x80);
_opcode = fetchScriptByte();
b = getVarOrDirectByte(0x80);
c = getVarOrDirectByte(0x40);
_opcode = fetchScriptByte();
d = getVarOrDirectByte(0x80);
unkRoomFunc4(b, c, a, d, 1);
break;
this opcode should actually redden the sky, its called 4 times for the 4 different shades of red.
comment:3 by , 23 years ago
Logged In: NO
i did some work on this and found out that this opcode is indeed need for a pal-manipulation (like a sunset).
the original script say something about:
------
[0000] (33) palManipulate(32,16,190,Local[0]))
[...] some code [...]
[0081] (33) palManipulate(32,16,190,1))
------
32, 16, 190, 1 are the same values which are also stored in a,b,c,d in the script_v1.cpp at this place (see post below). however, i've been unsuccessful to understand the true functioning of the palManipulate() method. my guess is that the values represent the rgb-colors, the pals involved and maybe a time delay (used to slowly fade one colour into another). i keep on working on this, but I'm not sure if i will solve it.
so far, trin
comment:4 by , 23 years ago
Logged In: NO
after some more reverse engineering, i found out that what the values in the original script by lucasarts mean.
palManipulate(32,16,190,Local[0]))
32 = color value 16 = all palettes from 1-16 190 = brightness/darkness (not sure about that one) Local[0] = time span for the effect (180 for the first call and 800 for the second in the closing scene)
comment:5 by , 22 years ago
Summary: | Indiana Jones extro playing incorrectly → FOA: Extro playing incorrectly |
---|
comment:6 by , 22 years ago
Thanks for the work, nobody, I am sure it'll be helpful to fix this - but of course if you can come up with a proper fix, that would be more than welcome, too :-)
I might look into this, once I have again a save game for the end.
comment:7 by , 22 years ago
I've upload a savegame from the original game for the closing scene.
btw: nobody = trinity just to lazy to login.
comment:8 by , 22 years ago
hehe OK :-) Anyway I have my own savegame now, too (I can't use save games that others made, I guess this is a en endian issue).
Anyway, unkRoomFunc4() is also called in script_v2. It would be nice if we collected more than this one space where it is used, so that we can get this done right.
comment:9 by , 22 years ago
Owner: | set to |
---|
comment:10 by , 22 years ago
Oh I just see it's a save game for the original. Well I doubt that my mac version of FoA can open it :-) In any case: could you possibly make some screen shots of the original game during the extro, then I have some visual reference whether I am doing this right so far or not.
comment:12 by , 22 years ago
Well, I am still waiting for screenshots of the original. Pretty hard to implement an effect if you don't know what it is supposed to look like :-)
I haven't looked into the music issue. Music seems to be quite problematic currently in general.
comment:13 by , 22 years ago
yeah, yeah, in know.
i'm really busy with real life issues at the moment, so i hadn't much time looking into it.
the problem is also, i don't how to take screenshots in a dos game. the windows print button doesn't work.
but i'll see what i can do, a little more patience please. :)
comment:14 by , 22 years ago
Owner: | removed |
---|
comment:15 by , 22 years ago
Impossible for me to work on this w/o any way to see the original. Sorry :-(
comment:16 by , 22 years ago
well im out of ideas here. as i said im not able to take screenshot in dos mode (i'm running win2k / win98), i tried various screengrabbers (pcxdump, snag it, ... some more) none worked. also i'm not sure if screenshots will really help, because a sunset is a progress and you need to see the sun move and slowly the sky turnig red.
i can't do much more than upload my savegame (which not worked for you). so the only solutions is that you finish (the original) indy 4 by yourself and see the sunset for yourself. don't you have any archives where you store savegames?
i could try to program it myself, but since i'm very busy at the moment and rather unfamiliar with the code, it chould take months, if i do not fail entirely. actually i'm a java programmer, with only basic knowledge of c++.
comment:17 by , 22 years ago
A screen shot would help me, even if it was taken while "in progress", because I coulde us it analyze just how the palette is changed (e.g. is just the red part changed, and how, stuff like that). I am fairly sure that I could make a pretty good approximation using 2-3 screen shots taken at different points.
Finishing the original Indy here is currently not a real option, as I have to reboot to Mac OS 9 to play it properly (well I can use it under OS X, but it's extremly bugged and forces me to switch to 256 color mode which slows down the system a lot).
Anyway, I think the first two parameters (16 and 190) specify the first and last color to be changed - the colors from 16-190 are exactly the ones used for waves/sky/clouds etc. I changed this in CVS accordingly and it seems pretty good.
I agree that 180/1/800 mean time - between the first and second call, roughly 18 = 180/10 seconds pass. So we need to do our work in this period.
I dunno about the other two parameters, though. The current change still just fade down the red part, but probably not enough. Another reason why a screen shot would help: I could see how it is supposed to look, roughly. <sigh> :-)
I do understand
comment:18 by , 22 years ago
Screenshots from DOS version are @ http://www.clock.org/~matt/scummvm . I couldn't attach files to an already submitted bug as a non- admin.
comment:19 by , 22 years ago
@matt
thx
@fingolfin
i'm not sure that your meaning about the "16" value is correct. my reverse engeneering attempts had different results. changes to the "16" value in the original foa (atlantis.000/atlantis.001) code, actually influence the areas where the pal-manipulation takes place. for example if you change the value to "8" only the upper half whould be affected by the pal-manipulation. so i found out that the screen is actually divided into 16 horizontal slices/levels (however you want to call it). changing the value to "3" whould result that only the upper 3 levels are affected by the pal-manip..
im not 100% certain about this (my test were 3 month ago), but i gonna double check it tonight.
comment:20 by , 22 years ago
Thanks, Matt.
Trinity: ah well, you never told us you did that, so how should I know :-)
I don't see how it should be possible to only affect the upper part of the screen by a palette change only - after all, the palette always affects the whole screen! But since the colors are "ramped", of course changing the value from 16 to something else will look as if only part of the screen is affected.
So I am certain it doesn't directly affect the area of palette change, simply because techincally it is extremly unlikely. Doesn't mean my guess at what it measn is right, either :-) So if you have some other ideas, speak up.
comment:21 by , 22 years ago
well i think i was mistaken, my mind is playing tricks on me :). i tested it again and it was not the same as in my memory. so ignore my previous post.
comment:22 by , 22 years ago
ok here are the results of my nightly reverse engineering session. i was able to take screenshots the same way matt did, which is a very annoying procedure. to take a screenshot, i have to switch to window mode, which crashes the game. so 10 screenshots = 10 crashs, 10 restarts, 10 load savegames. but nevertheless, here are the results, i hope the help you to figure out what the certain values are good for.
original lucas script code:
[0000] (33) palManipulate(32,16,190,Local[0])) //Local[0] = 180 and 800
[...] some code [...]
[0081] (33) palManipulate(32,16,190,1)) // this might be just a call to be sure that the pal-manip has finished, maybe to avoid problems with too slow cpu speeds. just a guess. ----------------------
chaning the first value (the 32-value) to 16 results in this:
http://domfree.de/trin/uploads/indy32to16-0.png http://domfree.de/trin/uploads/indy32to16-1.png http://domfree.de/trin/uploads/indy32to16-2.png
changing the second value (the 16-value) to 72 result in this:
http://domfree.de/trin/uploads/indy16to72.png
changing the second value (the 16-value) to 88 result in this:
http://domfree.de/trin/uploads/indy16to88.png
the last two screenshots show, how i came up with that slice/level idea, but now i think you are correct and is just coincidence.
i hope this helps you a little bit.
one last question (like columbo, hehe). fingolfin why does your pal-manipulation function has 5 parameters, while the one of lucasarts has only 4 parameters? is there a certain reason for this?
comment:23 by , 22 years ago
I encountered the same type of palette manipulation problem earlier in FOA, in the inner sanctum of Atlantis, when activating the big machine. The room is supposed to take on a reddish tint as the machine fires up and lava begins to flow.
In the August 25 daily build for Win32 (running on Windows 98 SE), a single, partial palette shift occurs halfway through the time period in which the transition would occur. In 0.2.0, even this partial transition does not occur.
Since I cannot submit files on a followup, I have sent them to fingolfin for review. Four files: two are before/after shots of the room from the original LEC executable, and two are before/after shots from the August 25 ScummVM daily build.
Finally, here are the errors produced in the console during this event:
WARNING: palManipulate(32, 65, 46, 20, 1): not implemented! WARNING: unkRoomFunc3(16,255,500,500,500): not fully implemented!
Since this is just a single manipulation and not TWO manipulations like the end sequence is reported to be, perhaps it will be a bit easier to figure out what the palette changes are supposed to be like.
Hope this helps....
comment:24 by , 22 years ago
Very useful information indeed! Now we have an additional test case, and more test data.
E.g. it's now obvious that one of my guess (that 16-190 is a range) can't be correct, as here the range would be 65-46, which doesn't make sense at all.
I attached the two screen shots from the original version.
comment:25 by , 22 years ago
Stupid little me, of course the range would be 32-65, which could be right. Need to verify if it would match the palette.
comment:26 by , 22 years ago
Don't know why people say the Windows PrntScrn button doesn't work with FOA. Works fine for me, except that it transforms the capture to 640x400 True-Color.
Anyway, I downloaded a capture utility to do native VGA captures, so the original 256-color palettes would come through. I have uploaded native VGA captures of the inner sanctum "Big Machine" scene (before/after shots) to fingolfin for review.
The palette range that seems to be affected does indeed seem to be something coinciding with, or very close to, the 32-65 range. In addition, I timed the color transition, and it takes about 2 seconds to complete (the 20 in our palManipulate call?).
I'm looking at the exact nature of the palette changes now to try to figure out how diverse target colors can be specified using a single parameter (the mysterious 46 in the palManipulate call for the "Big Machine" scene). Or is it possible that additional useful information is included in the unkRoomFunc3 incident that seems to accompany every palManipulate call? I'll ponder that too.
I feel like I'm putting Indy in danger over and over, each time I activate that big machine for test purposes. ;-)
comment:27 by , 22 years ago
Never mind about unkRoomFunc3 occurring along with palManipulate calls. I just played through to the end, and it didn't show up at all during the extro. Just 4 calls to palManipulate, showing up in the August 25 Daily Build console window as such:
Loading room 96 [extro scene] WARNING: palManipulate(16, 190, 32, 180, 1): not implemented! Time since last call: 346559 WARNING: palManipulate(16, 190, 32, 1, 1): not implemented! Time since last call: 17184 WARNING: palManipulate(16, 190, 32, 800, 1): not implemented! Time since last call: 9983 WARNING: palManipulate(16, 190, 32, 1, 1): not implemented! Time since last call: 75353 Loading room 68 [closing LucasArts logo]
I'm only reporting on what shows up in the console window, not opcodes that are recognizable and processed without alerts. Are there surrounding opcodes that provide more information about the target palette for transitions? ScummVM *does* change the palette, but they are instantaneous changes, and I don't know where the target palette is coming from.
comment:28 by , 22 years ago
First check out the changes I commited to CVS just now :-) In scumm/gfx.cpp, you can find palManipulateInit() which does the current (wrong) effect, just a hack. There is also palManipulate() which apparently is not having any effect as the variables that steer it are nowhere inited, nor are the rtTemp buffers existant. So I think somebody disassembled those but never hooked them up?
In any case, I also had a look at the original data file using a data browser, and know what, the CLUT there doesn't match the "new" nor the "old" palette (i.e. before/after the effect) jamieson sent me.
So my guess is that what actually happens might not be a purely computed effect, but rather a transition to a different palette. I'll try to hook up into palette modifying procs to check what exactly goes on.
comment:29 by , 22 years ago
OK, in the Inner Sanctum, the palette is changed by the script: the colors from 32-65 are changed "manually" by calls to setPalColor. As a consequence, if I just restore the "original" room palatte, it looks right (changing this to "fade" the palette is the simplest part, let's do that later).
However that doesn't work at all for the extro, I couldn't detect any palette changes there, and the original room palette is the starting one (daylight). And in any case, here we have to fades, first it reddens as the sub sets, then it gets night, and the starts comes out.
by , 22 years ago
Attachment: | reverseeng.zip added |
---|
the screenshot from the reverse engineering session, see post in this thread to understand their meaning
comment:30 by , 22 years ago
Another point of interest is that in the extro, palManipulate is doing its work on colors that themsleves are shifting. The water is constantly changing, while at the same time following the general lighting fades that palManipulate is supposed to be effecting. Whether the water is animated or based on a palette cycle, I'm not sure. If the latter is true, it would be evidence that palManipulate is based on math transformations rather than target palette information.
I'm dumping and de-SCUMMing the scripts right now to start really digging into this. Let's see how far I can get with the next 5 days off. ;-)
comment:31 by , 22 years ago
palManipulate works by slowly fading a given source palette into a target palette. Look at file gfx.cpp, palManipulate and palManipulateInit.
If cycling is active, it is not only being applied to the current palette, but also to the target pal - moveMemInPalRes is responsible for that.
That is, that's how it is supposed to work. The only puzzle piece which is missing is how to acquire the "target palette data". That's why, if you look closely, palManipulate and moveMemInPalRes are not doing anything right now. Of course, I could change that to at least to a proper fade to the (currently wrong) target palette. But the realy "mystery" is: how do we generate the target palette?
I did compare the target and source palettes in the original came. As a result, I am fairly convinced that this is not being done by a mathematical function, at least not without some big additional lookup table (i.e. static data). Hence it is much more likely (as it is simpler) to assume that they somehow use a second different palette as data, instead of a math function.
Of course, I can not 100% exclude the possibility of a math function. Disassembling the original code would be the "easiest" way to find out for sure.
comment:32 by , 22 years ago
Okay, here's the missing puzzle piece. palManipulate gets its target palette from STRINGS.
Three strings, specifically. The first string specifies the red values, the second string specifies the green values, and the third string specifies the blue values. The strings must have contiguous ID numbers, e.g. 32 (red), 33 (green) and 34 (blue). The first ID number is referenced in the palManipulate call, and the other two are inferred.
In the Inner Sanctum (room 23), the following scripts are relevant (these are script numbers, not resource offsets, since I'm working off of SCUMMVM dumped scripts):
Script 166 is the script that executes when Indy manages to turn on the big machine. At the point where the lighting changes, Script 171 is called. Script 171 starts off like this:
[0000] (27) PutCodeInString (46, "@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@") ; [0053] (27) PutCodeInString (47, "@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @"); [00A7] (27) PutCodeInString (48, "@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@"); [0100] (27) SetStringChar(46,32,243) [0105] (27) SetStringChar(46,33,251) [010A] (27) SetStringChar(46,34,251) [010F] (27) SetStringChar(46,35,251) [0114] (27) SetStringChar(46,36,251) [0119] (27) SetStringChar(46,37,251) [011E] (27) SetStringChar(46,38,251) [0123] (27) SetStringChar(46,39,243) ....
Three strings. Initialized to dummy characters so that each character can subsequently be replaced with direct numbers (that may or may not be representable by printable characters). The code goes on to initialize string IDs 46, 47 and 48 with the red, green and blue colors for the reddish room (which, as fingolfin pointed out, corresponds to the intial palette of the room anyway).
The call to palManipulate, at the end of a long sequence of string character setups, is as follows:
[02FF] (33) palManipulate(46,32,65,20))
The first parameter, the one we haven't been able to identify, is in fact the ID of the first of the three strings from which to glean the target palette data.
Okay, now let's look at the troublesome extro sequence, which is Room 96.
There are TWO palManipulate calls, executed by Room 96 localized Script 201. Both calls reference the same base string ID of 32:
[0000] (33) palManipulate(32,16,190,Local[0])) .... [0081] (33) palManipulate(32,16,190,1))
However, no strings are set up in this script. In fact, this script is being monitored by a parallel script, Room 96 localized Script 200. Here are the interesting lines for Script 200:
[002E] (0A) startScript(157,[]) [0031] (80) breakHere() [0032] (68) Var[0] = getScriptRunning(157) [0036] (28) if (Var[0]) goto 0031; .... [006D] (2A) startScript(201,[180]) .... [007C] (80) breakHere() [007D] (68) Var[0] = getScriptRunning(201) [0081] (28) if (Var[0]) goto 007C; [0086] (0A) startScript(158,[])
This section of script runs global Script 157, makes sure its completed its stuff, then runs the Script 201 we just talked about. It then waits for a break in 201 before running Script 158.
Scripts 157 and 158 each contain -- you guessed it -- string intializations! Both of them initialize strings 32, 33 and 34 with numeric data. Script 157 sets the strings to our "middle" or "twilight" palette, and must get the strings all ready before 201 starts. Once 201 is in progress, BUT before it gets to the second palManipulate, script 158 is called by 200 to set up strings 32, 33 and 34 to our "final" or "nighttime" palette. By the time 201 gets around to its second palManipulate, the strings are ready to rock and roll.
To test that these strings were, in fact, being instantiated with the target palettes we've been searching for, I pulled the code out and stripped it down to the basic numbers, then plugged those directly into the palette area of a PCX image representing the start of the extro (i.e. the "initial" or "daytime" palette). I am sending the resulting 256-color images to fingolfin for review.
Note that for the extro, colors for EVERY palette entry are entered into the three strings, even though only palette entries 16 through 190 are making the transition. Also note that the strings CAN be less than 256 characters long if not all the colors are to be changed, BUT each string must be at least as long as the highest color index that will be manipulated. (In the Inner Sanctum, strings 46, 47 and 48 are actually 79, 80 and 85 characters in length, even though only characters 32 through 65 are being set to anything. Weird, huh?)
I hope this helps! Gorgeous Indy sunset, here we come! ;-)
comment:33 by , 22 years ago
Slight correction -- Room 96 Script 201 executes palManipulate twice for the same palette. The first call is to do the transition, the second call is to force the transition to happen immediately, if for some reason it hasn't already reached its target palette.
Room 96 Script 200, which controls the calls to 157, 158 and 201, calls 201 twice, once for the "twilight" palette (transition from "daylight" in 180 tenths-of-a-second) and once for the "nighttime" palette (transition from "twilight" in 800 tenths- of-a-second).
[002E] (0A) startScript(157,[]) [0031] (80) breakHere() [0032] (68) Var[0] = getScriptRunning(157) [0036] (28) if (Var[0]) goto 0031; .... [006D] (2A) startScript(201,[180]) .... [007C] (80) breakHere() [007D] (68) Var[0] = getScriptRunning(201) [0081] (28) if (Var[0]) goto 007C; [0086] (0A) startScript(158,[]) ... [009C] (2A) startScript(201,[800,1])
So the wait for Script 201 is actually to wait for it to COMPLETELY end, not to slip a call to 158 into the middle of 201's execution. Sorry for the mixup; I think I've been staring at hex a little too long this evening. ;-)
comment:34 by , 22 years ago
Owner: | set to |
---|---|
Resolution: | → fixed |
Status: | new → closed |
comment:36 by , 22 years ago
well, the music issue still remains, but i can open a new bug report for this :)
finally this bug closed, great job everyone !
I can confirm that this is not a machine specific problem, as I've encountered it too, except under Windows XP Professional (build 2600)