Community

SCI Programming => SCI Syntax Help => Topic started by: doomlazer on January 07, 2026, 06:27:37 PM

Title: solitary vaules in QfGIV changeStage switch statement
Post by: doomlazer on January 07, 2026, 06:27:37 PM
What's the purpose of the solitary vaules such as this from QfGIV rm340 (https://github.com/EricOakford/SCI-Decompilation-Archive/blob/36f8aeb4a2f6e5ec95eec91e12810bbef55357ba/qfg4cd/src/rm340.sc#L690):

Code: [Select]
(method (changeState newState)
(switch (= state newState)
(0
0 ; THE VALUE IN QUESTION
(theGame handsOff:)
(if (and (== (barrel x?) 116) (not (Btst 254)))
(self changeState: 6)
else
(= cycles 1)
)
)
...

I've looked at 'setScript' and some other possibilities and maybe it's setting the register value or something, but found nothing conclusive. Honestly, it just doesn't make sense to me.

They appear in both EO's and Sluice's decompile repos, so I don't think it's a mistake. Anyone know?
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 07, 2026, 09:18:48 PM
I have seen these in Longbow, which was apparently written by some interns. The compiler was lenient enough to allow it, and the final code worked. These interns were named (there are names in the credits you don't see anywhere else). So it's possibly an intern.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: doomlazer on January 07, 2026, 09:31:56 PM
Ok, that's a satisfying enough explanation for me. TY
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 08, 2026, 03:33:30 AM
If I had to make a technical guess, having a bare expression like that might serve to set the PMachine's accumulator.

Now, we don't know what the original code looks like, whatever caused this code
Code: [Select]
0e69:35 00            ldi 0 //That's him, officer!
0e6b:38 0216          pushi 216 // $216 handsOff
0e6e:76               push0
0e6f:81 01            lag theGame
0e71:4a 0004          send 4
but I can imagine why our decompilers would include that mystery value.

Still, all it does is set the accumulator, which is then replaced with a pointer to the game. However it got in there, it does nothing.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 08, 2026, 02:36:26 PM
And the Longbow code I was thinking of is this:
Code: [Select]
       (method (changeState newState &tmp temp0)
                (switch (= state newState)
                        (0               
                                (HandsOff)                             
                                (if (not (IsFlag 129))         
                                        (NormalEgo)
                                )                       
                                (switch register               
                                        (1       
                                                (cond
                                                        ((== local0 220)
                                                                (cond           
                                                                        (21     
                                                                                36
                                                                                37
                                                                                38
                                                                                50
                                                                                56
                                                                                67
                                                                                75
                                                                                98
                                                                                99
                                                                                103
                                                                                115
                                                                                119
                                                                                135
                                                                                167
                                                                                (if
                                                                                        (and
                                                                                                (> (gEgo x:) 35)
                                                                                                (< (gEgo x:) 150)
                                                                                        )
                                                                                        (= global104 155)
                                                                                )
                                                                        )
                                                                        (
                                                                                (and
                                                                                        (> (gEgo x:) 170)
                                                                                        (< (gEgo x:) 285)
                                                                                )
                                                                                (= global104 165)
                                                                        )
                                                                )
                                                        )
This should most likely have been (if (OneOf gForestRoom blah) blah) because there are numerous of those in the script. Typo, cut/paste error, or intern.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 08, 2026, 02:47:45 PM
How the hell is that supposed to work?! I wouldn't know what that's supposed to do if you hadn't brought up the OneOf thing. There's no way that code works the way it supposedly should.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 08, 2026, 07:15:28 PM
One more, from the same script:
Code: [Select]
                (LoadMany
                        rsVIEW 
                        805
                        792
                        764     
                        763
                        230
                        231     
                        232
                        233
                        234
                        235
                        236
                        237
                        238
                        (if (== gDay 2)
                                214
                                218
                                16
                                4         
                                5
                                7
                                585
                        )
                        (switch gDisguiseNum
                                (0 ; outlaw
                                        0
                                        1
                                        2
                                )
                                (1 ; beggar
                                        36
                                        37
                                        38
                                )
                                (2 ; jewler (no rouge)
                                        29
                                        30
                                        31
                                )
                               (3 ; jewler (rouge)
                                        29
                                        30
                                        31
                                )
                                (4 ; yeoman
                                        33
                                        34
                                        35
                                )
                                (5 ; abbey monk
                                        23
                                        24
                                        27
                                )
                                (6 ; fens monk
                                        16
                                        17
                                        18
                                )
                        )
                )
Someone who knows the PMachine knows that that won't work.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 09, 2026, 05:47:53 AM
Load all of these, and in this particular case also these? Forget the PMachine, that's a script-level mistake.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: troflip on January 09, 2026, 12:11:59 PM
I'm more curious what the original source code looked like that ended up compiling to that. Do any of the games that have had the original code released (there are a few I think, like maybe one of the LSLs?) have logic like that?
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 09, 2026, 12:40:02 PM
All I have is Larry, and I'm pretty sure they don't.

The first instance with the same intent as the Longbow example would be LSL1 room 320, where the dancers or comedian and drummer are loaded along with the rest. But those are separate LoadMany calls with some distance between them. Same deal in rooms 350, 370, and 390. Then in LSL5 I see similar constructs all over.

If I were to ascribe to the "silly interns" theory, I'd say they misunderstood how sub-expressions (putting an if or switch in the middle of the argument list for OneOf or LoadMany) works. Clearly, Brian K. Hughes, Juan Carlos Escobar, and John Hartin knew what they were doing (except for BKH messing up the Hollywood sign feature in room 190 lol)
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Collector on January 09, 2026, 03:56:03 PM
Omer hasn't been around, lately. I wonder if he has any of the original sources in question.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 09, 2026, 04:33:57 PM
Just for fun, I replicated the basic premise in isolation:

Setup
Code: [Select]
(procedure (Test)
  (TestHelper
    1 2 3
    (if (== gTest 2)
      4 5 6
    )
    7 8 9
  )
)
Code: [Select]
(procedure Test
  pushi 7 // argc
  push1 // push the first three values to the stack
  push2
  pushi 3

  lsg gTest // push gTest
  ldi 2 // load 2 to acc
  eq?
  bnt nope
  ldi 4 // load to acc, not push
  ldi 5
  ldi 6

nope:
  push // push acc to stack

  pushi 7 // push the rest
  pushi 8
  pushi 9
  call TestHelper 14
)

Result from TestHelper
When the test fails:
Code: [Select]
0 = 1
1 = 2
2 = 3
3 = 0 <-- ?
4 = 7
5 = 8
6 = 9
When the test succeeds:
Code: [Select]
0 = 1
1 = 2
2 = 3
3 = 6 <-- !
4 = 7
5 = 8
6 = 9

Takeaways:
1. We try to supply either six or nine items, but only ever push seven values. argc being 7 and the call looking back 14 bytes says as much.
2. If the test fails, we still push whatever is in acc! Values 4 and 5 are wasted.
3. This is not only Technically Valid code, but also even more hilariously broken at runtime than I expected!
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: troflip on January 09, 2026, 07:11:17 PM
If this is SCI Companion, the success case seems correct anyway. The value of a section of code is the last thing in that code, so 6 in this case. There should be 7 params, because the if statement resolves to a single param.

Not sure if it's "defined" what the value of a condition expression will be if there is no else, but it seems like it will always be the result of the last acc value that was branched on, 0.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: Kawa on January 10, 2026, 04:33:56 AM
I just tried it myself. A switch instead of an if gave the expected, similar results, just with the PMachine equivalent of a switch.
Code: [Select]
(ListAll
  1 2 3
  (switch gTest
    (0
      ; Left blank for fun
    )
    (1
      4 5 6
    )
  )
  7 8 9
)
Always seven values, and the fourth is either 6 or leftovers.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: doomlazer on January 10, 2026, 12:53:11 PM
Great. This will be a pattern I use in my own fan mods from now on. :)
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 10, 2026, 08:38:07 PM
Of course, one could imagine a pushlist keyword that would actually do this properly. It would only work if the branches of the if/switch all had the same number of elements (as in the disguise part of the above), otherwise an enhancement to the PMachine would be needed. That would be an advanced usage, because it can potentially corrupt the stack.
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 10, 2026, 08:47:03 PM
I'm more curious what the original source code looked like that ended up compiling to that. Do any of the games that have had the original code released (there are a few I think, like maybe one of the LSLs?) have logic like that?
Probably used those long defines that Companion doesn't support. Sometimes Sierra had two versions of such defines which were subtly different. Maybe mistaking one for the other?

(or rather, I know that this is it. Some of the other OneOf calls have the exact same list of room numbers. Had to come from a define.)
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: doomlazer on January 12, 2026, 10:04:52 PM
Sluicebox managed to trackdown the cause, at least for the code I originally posted about. It's from using case values with switchTo.

SwitchTo (https://scicompanion.com/Documentation/Compiler/switchto.html) doesn't use case values; adding them compiles fine, but leaves behind the garbage. You can see switchTo was used in the LSL1VGA source with case values (https://github.com/historicalsource/leisure-suit-larry-1-vga/blob/13c82564d95c5253283b3dcf95715750a27af456/SRC/300.SC#L429), which results in the extra values when decompiled (https://github.com/sluicebox/sci-scripts/blob/12c1ab894c4bd5fbf4157eb18a9e86653ec15d1b/lsl1-dos-2.1/src/rm300.sc#L309).

switchTo is used quite a bit in lsl1vga, and not always incorrectly either!

edit: fixed link
Title: Re: solitary vaules in QfGIV changeStage switch statement
Post by: lskovlun on January 13, 2026, 09:54:09 AM
That's a nice find. And switchto was a late addition to the SCI language, so it makes sense.