Author Topic: SQ5 preliminary decompiled source  (Read 28511 times)

0 Members and 1 Guest are viewing this topic.

Offline Collector

Re: SQ5 preliminary decompiled source
« Reply #15 on: May 05, 2015, 03:17:09 AM »
If the patch is the one that I am thinking if, it is a patch that adds the diskette version's graphics to the MPC release. If it is, it uses the CD's interpreter, which is SCI1.1.
KQII Remake Pic

Offline lance.ewing

Re: SQ5 preliminary decompiled source
« Reply #16 on: May 05, 2015, 04:30:29 AM »
Would they have been doing a lot of conversion/refactoring for the first SCI game? I may be wrong, but I thought that KQ4 was purposely written for SCI and the AGI was co-developed.

I don't know. You're probably right. The AGI version of KQ4 was quite an investment for something that probably didn't sell very well. It might even be the pinnacle of AGI development. If they focussed on one and converted to the other then it might have saved a lot of time. But maybe they developed them separately.

Offline MusicallyInspired

Re: SQ5 preliminary decompiled source
« Reply #17 on: May 05, 2015, 07:50:12 AM »
Collector's correct. It's the CD version which is SCI1.1. However, I discovered that his patch does not include the Time-O-Matic time warp after all, it was another script written by someone called the "Time Pod Debug patch" available on the archived SQ.Net website. So I sent you the wrong one anyway. Here's where you can get it. http://www.spacequest.net/archives/sq4/cheatdebug/
Brass Lantern Prop Competition

Offline Cloudee1

Re: SQ5 preliminary decompiled source
« Reply #18 on: May 05, 2015, 08:05:45 AM »
Phil,  I assume you have noticed this already but just in case, I figured I would point it out too

Case statements... they seem to include an extra set of parenthesis inside the actual cases. This came out of room 100 but it is looking like it is the same throughout

Code: [Select]
            (case 0
                (
                (send gSq5Music1:number(1001)loop(1) play())
                 (sparkle:init())
                 = seconds 4
                )
            )
Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline troflip

Re: SQ5 preliminary decompiled source
« Reply #19 on: May 05, 2015, 12:12:48 PM »
Collector's correct. It's the CD version which is SCI1.1. However, I discovered that his patch does not include the Time-O-Matic time warp after all, it was another script written by someone called the "Time Pod Debug patch" available on the archived SQ.Net website. So I sent you the wrong one anyway. Here's where you can get it. http://www.spacequest.net/archives/sq4/cheatdebug/

Ok, that one worked. The only difference is that the (cables:init()) has been replaced by (frog:init()). It's difficult to change the lenght of a script if you're just directly editing bytecode, so it makes sense that he had to "replace" one object with another.
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline MusicallyInspired

Re: SQ5 preliminary decompiled source
« Reply #20 on: May 05, 2015, 12:22:17 PM »
Ah interesting. I imagine that the line still won't work, however, since restOfPod supercedes it, right?
Brass Lantern Prop Competition

Offline troflip

Re: SQ5 preliminary decompiled source
« Reply #21 on: May 05, 2015, 01:11:31 PM »
Phil,  I assume you have noticed this already but just in case, I figured I would point it out too

Case statements... they seem to include an extra set of parenthesis inside the actual cases. This came out of room 100 but it is looking like it is the same throughout

Cool, thanks! I hadn't noticed (maybe because it was actually random if it happened - uninitialized memory). I just made a fix.
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline lskovlun

Re: SQ5 preliminary decompiled source
« Reply #22 on: May 05, 2015, 01:39:03 PM »
Ah interesting. I imagine that the line still won't work, however, since restOfPod supercedes it, right?
No, this should work just fine. The initialization order goes like this (excluding some more complex initializations that come before these, and things that aren't features):
Code: [Select]
        (rogerHead:init())
        (keyDisplay:init())
        (mainScreen:init())
        (smallCompartment:init())
        (largeCompartment:init())
        (headRest:init())
        (cables:init())
        (entryPad:init())
        (exitButn:init())
        (restOfPod:init())
What happens is that these go into an ordered list. If frog is substituted for cables, then it will indeed come before restOfPod. What I was doing was I added it manually by calling frog::init from the ScummVM debugger, in which case frog goes in last. In that case, restOfPod must be removed for things to work.
« Last Edit: May 05, 2015, 01:40:48 PM by lskovlun »

Offline MusicallyInspired

Re: SQ5 preliminary decompiled source
« Reply #23 on: May 05, 2015, 02:44:39 PM »
Ah. Strange, then, as I still can't seem to trigger it...
Brass Lantern Prop Competition

Offline MusicallyInspired

Re: SQ5 preliminary decompiled source
« Reply #24 on: May 05, 2015, 06:02:02 PM »
Here's a question, I found this global procedure in the SQ4 Main script. I'm trying to figure out what another action does elsewhere in the game as it bases what it does on whether this procedure returns 1 or 0. I understand that the & operator is comparing two things and if their bits both equal 1 it returns 1, but I don't know what's going on between those two values, what they resolve to, or what they're supposed to represent. I also don't know what global114 is supposed to be. Any ideas?

Code: [Select]
(procedure public (proc0_6 param1)
    return & global114[(/ param1 16)] (>> $8000 (% param1 16))
)

Two other global procedures utilize this code as well.
« Last Edit: May 05, 2015, 06:05:19 PM by MusicallyInspired »
Brass Lantern Prop Competition

Offline lskovlun

Re: SQ5 preliminary decompiled source
« Reply #25 on: May 05, 2015, 06:23:58 PM »
Here's a question, I found this global procedure in the SQ4 Main script. I'm trying to figure out what another action does elsewhere in the game as it bases what it does on whether this procedure returns 1 or 0. I understand that the & operator is comparing two things and if their bits both equal 1 it returns 1, but I don't know what's going on between those two values, what they resolve to, or what they're supposed to represent. I also don't know what global114 is supposed to be. Any ideas?

Code: [Select]
(procedure public (proc0_6 param1)
    return & global114[(/ param1 16)] (>> $8000 (% param1 16))
)

Two other global procedures utilize this code as well.
Oh, this is a pattern you'll see quite often in SCI1/SCI1.1 - the scripts often use bit flags instead of variables to denote whether a particular event has occurred.
There are three procedures that you will first need to identify - test, set and clear (this one tests the specified flag). Once you've done that, stop focusing on the code in these procedures and instead look at the parameter it's called with. This parameter is a flag number. So in whatever code you're looking at, the flag with that number is being tested - has this event occurred yet, has the player performed a particular action yet, etc. You can try to find the corresponding call that sets the flag (use findstr or whatever tool you have for searching through files; your knowledge of the game itself may also provide clues).

Offline troflip

Re: SQ5 preliminary decompiled source
« Reply #26 on: May 05, 2015, 06:34:55 PM »
I think it might be an efficient way to store important game flags. Normally every variable (even if it's just an on/off flag) takes up 16 bits. This way it only takes up 1.

When you see a / and % operator together, that's usually because someone is trying to split a number into two parts... the quotient and the remainder.

So say param1 is 37. Then we'll get 2 for the quotient (37 / 16), and 5 for the remainder (37 % 16). Then it will return what is in bit 5 of array index 2.

Looks like proc0_7 and proc0_8 are responsible for setting and clearing those bits.
I think did something similar when I made Cascade Quest, so that I could save space for game flags.

My decompiler wasn't able to ascertain any name for the variable.

I do have the ability to detect arrays, but I turned it off for the global script. I can detect arrays based on how the variable is used. But it just scans the current script for variable usage. To see how globals are used I need to scan all the scripts at once. It's probably not too hard to do that.

Just doing a quick string search, it looks like the next variable that is used anywhere after global114 is global128. So that suggests global114->global127 is an array. So ideally the decompiler would produce code like this:

Code: [Select]
...
gStopGroop
global114[14]
global128
...

And 14 spots of 16 bits each suggests SQ4 handles up to 224 game flags.

[edit... ninja'd by Lars :-)]

The piece of source code from PQ SWAT calls a Bset procedure, which presumably stands for "bit set". So "good" names (to stay true to the original source code) would maybe be Btest, Bset and Bclear.

I attached the SQ4 source code with those changes...
« Last Edit: May 05, 2015, 06:53:57 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline MusicallyInspired

Re: SQ5 preliminary decompiled source
« Reply #27 on: May 05, 2015, 06:59:14 PM »
Very illuminating! Thank you both. Here's the block of code I'm trying to decipher. I'm trying to figure out how another line is called in a script. Specifically in the center screen on the Xenon streets, when the ship is parked on the ground, interacting with gear1 or flap (the gear flap) will either cause Roger to enter the ship and take off or, if something is tested with proc0_6(), return the message "You're starting to show your age." I'm not sure how to trigger it because I'm not sure what proc0_6() is testing.

This is the doVerb method of the flap Prop. I added some observations and questions as comments:
Code: [Select]
(method (doVerb param1)
    (switch (param1)
        (case 2
            (if (Btest(0))              // No idea what this is testing. I don't know what the global114 array is supposed to represent, it's only used in the Main script and no where else
                (if (not script)            // I guess this is checking if there is a script set for the room?
                    proc0_2()                 // This removes control from the player
                    (send global2:setScript(egoHides))      // Animates Roger entering the ship
                )(else
                    Print("You're starting to show your age.")
                )
            )(else
                (super:doVerb(param1))                          // Not sure....? It looks like it's retriggering itself. Why won't this enter an infinite loop?
            )
        )
        (default
            (super:doVerb(param1))                             // Same as above
        )
    )
)
« Last Edit: May 05, 2015, 07:05:34 PM by MusicallyInspired »
Brass Lantern Prop Competition

Offline troflip

Re: SQ5 preliminary decompiled source
« Reply #28 on: May 05, 2015, 07:29:21 PM »
It's testing if flag 0 is set. I did a search for Bset(0), the only hit for that is in rm040.sc. It looks like it's set if the ego came from some room other than north (25), south (55) or east (45).

It looks like my decompiler named the "previous room number" global "gWest", due to an assignment to that variable in rm535.sc. Oh well... can't be perfect.

It doesn't look like any other room *directly* connects to room 40 other than those three. However, searching for "newRoom(40)" shows that this is called in rm072.sc. So presumably going from room 40 via room 72 will set that bit (flag 0).
Check out my website: http://icefallgames.com
Groundhog Day Competition

Offline troflip

Re: SQ5 preliminary decompiled source
« Reply #29 on: May 05, 2015, 07:43:16 PM »
Incidentally, as you're looking through these scripts, I could use feedback on what additional information would be useful for understanding the scripts.

For instance, this
(if (& (send gEgo:onControl(1)) $0080)
would be nicer if it were:
(if (& (send gEgo:onControl(1)) ctlSILVER)

Likewise, in the snippet you posted, "case 2" should really be "case vbLOOK", or whatever verb 2 is (maybe someone could figure out which verbs correspond to which numbers? Is it the same across different games?)

I'm trying to decide whether or not to just have a few hard-coded heuristics for stuff like this, or go for a more flexible system that can read the mapping from some config file.
« Last Edit: May 05, 2015, 07:59:16 PM by troflip »
Check out my website: http://icefallgames.com
Groundhog Day Competition


SMF 2.0.19 | SMF © 2021, Simple Machines
Simple Audio Video Embedder

Page created in 0.032 seconds with 23 queries.