Simplifying "Leisure Suit Larry 2"'s Copy Protection
I’m continuing my series of posts where I patch old Sierra games to simplify their copy-protection tasks. Today, it’s the little black book challenge to get into LSL2. If it’s like the other games so far, I don’t expect it to be terribly difficult, but we’ll see!
As a reminder: I don’t really want to bypass the copy protection. I like seeing it; it’s a nostalgia thing. I just don’t want to have to get the answer correct to get to the other side of it.
The patch I produced is at the bottom of this post.
Getting Started
As before, I used the excellent SCI Companion software, rather than write my own decompiler–though I will probably do that one day for fun.
To start, I decompiled all the game scripts, and searched through the text for hints as to were the copy protection scheme was. It turns up as text number 10.

… which means we need to look at the script for room 10.
The Protection Scheme
The copy protection scheme is very similar to the other games. First, a random number is generated to drive hard-coded question parameters and answer strings:
(switch (= local0 (Random 1 16))
(1
(= local1 0)
(= local2 5)
(= local3 1)
(= local4 4)
(= local5 7)
(= local6 {555-7448})
)
... elided the rest,,,
)
Then, after displaying the question and collecting the user’s input into global170,
it checks the answer:
(cond
((not (StrCmp @global170 {555-0724})) (= global100 1) (global2 newRoom: 23))
((not (StrCmp @global170 local6)) (global2 newRoom: 90))
(else
(proc255_0 10 3)
(if local8 (proc255_0 10 4) else (= global4 1))
)
)
This is extremely similar to the King’s Quest IV scheme, in that:
global4records whether the user got the correct answer. Actually I think all of the SCI games usedglobal4for this.- There is a hard-coded, always-correct answer of
555-0724, which bypasses the intro and dumps you into the game. This has to be to help playtesters or debuggers.
So, just like KQIV, I’m going to just change the entire cond expression into a call
to (global2 newRoom: 90). Here’s the disassembly of that portion of the code:
058d:7a push2
058e:5b 00 aa lea 0 aa
0591:36 push
0592:72 0132 lofsa $06c7 // 555-0724
0595:36 push
0596:43 49 04 callk StrCmp 4
0599:18 not
059a:30 0011 bnt code_05ae
059d:35 01 ldi 1
059f:a1 64 sag global100
05a1:38 00e4 pushi e4 // $e4 newRoom
05a4:78 push1
05a5:39 17 pushi 17 // $17 name
05a7:81 02 lag global2
05a9:4a 06 send 6
05ab:32 0039 jmp code_05e7
code_05ae
05ae:7a push2
05af:5b 00 aa lea 0 aa
05b2:36 push
05b3:8b 06 lsl local6
05b5:43 49 04 callk StrCmp 4
05b8:18 not
05b9:30 000d bnt code_05c9
05bc:38 00e4 pushi e4 // $e4 newRoom
05bf:78 push1
05c0:39 5a pushi 5a // $5a isKindOf
05c2:81 02 lag global2
05c4:4a 06 send 6
05c6:32 001e jmp code_05e7
code_05c9
05c9:7a push2
05ca:39 0a pushi a // $a nsLeft
05cc:39 03 pushi 3 // $3 y
05ce:47 ff 00 04 calle ff procedure_0000 4 // proc255_0
05d2:83 08 lal local8
05d4:30 000c bnt code_05e3
05d7:7a push2
05d8:39 0a pushi a // $a nsLeft
05da:39 04 pushi 4 // $4 x
05dc:47 ff 00 04 calle ff procedure_0000 4 // proc255_0
05e0:32 0004 jmp code_05e7
code_05e3
05e3:35 01 ldi 1
05e5:a1 04 sag global4
code_05e7
05e7:48 ret
… so I just copied the code for the call followed by a RET (0x48) into that spot:

… and it works! I can type anything in now, and it lets me through:

The Patch
Just put this script.010 patch as script.010 in
your game directory, and it should work.
It’s nice that this change is specific to the copy protection script, because it gives some confidence that the overall game isn’t broken by the change I made. Also, none of the original game assets were modified. That’s the nice thing about the SCI engine… it looks for uncompressed overrides of the in-game scripts on the file-system. If you delete the patch file (or rename it), the game will resume checking your answer.