Simplifying "Leisure Suit Larry 3"'s Age Protection
I’m continuing my series of posts where I patch old Sierra games to simplify their copy-protection tasks. Today, it’s the age quiz challenge to pick a raunchiness-level in LSL3. I expect this one to be a little different than the other SCI games (maybe closer to LSL1).
As a reminder: I don’t really want to bypass the age 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. Before long I spot the lists of questions in texts 141 to 160 or so. Also, it jumps out right away that the correct answer is encoded with the question:

You can see that a number precedes the questions, indicating which answer is correct. The code for the game obviously strips that off before displaying it.
Text 140 has the actual control logic, based on the texts:

So, next I’ll check out Script.140…
The Protection Scheme
As with my LSL1 patch, I want the game to tell me if I get the questions right or wrong,
but then give me credit anyway. So, that’s the angle I’ll be looking for as I inspect the
code.
Right away, I know it will be slower going this time because the decompiler failed on a large part of this script. So, I’ll have to slog through plain disassembly instead. Just skimming through the file, I note a few things right away:
- This code reads and/or writes to two different files, going by the
names of calls like
FOpen.LARRY3.DRVappears to hold 3 pseudorandom numbers. Maybe their purpose is to keep from giving out the same questions twice in a row? I’m not sure.RESOURCE.LL3has a number in it, which might be related to the ultimate raunchiness level you attain. Maybe it will become clear during this investigation. (EDIT: Yep,Room 290reads this file right afterRoom 140writes it out, and stores the number inglobal124, which I can see is what the game tests for raunchiness level. Maybe the testers would keep a read-only file with the number they wanted to achieve in it? I don’t know.)
- It looks like maybe
local2will ultimately hold your score… this code jumped out at me, since it keep comparinglocal2to numbers and assigning the level strings based on them:
pushi 11
lsl local2
dup
dup
ldi 5
eq?
bnt code_05f4
lofsa {Totally Raunchiest}
jmp code_061e
code_05f4:
dup
ldi 4
eq?
bnt code_0601
lofsa {Really Filthy}
jmp code_061e
code_0601:
dup
ldi 3
eq?
bnt code_060e
lofsa {Pretty Dirty}
...etc...
So, with that clue, let’s see what else happens with local2… next up, they
subtract 1 from it and write it to a file named RESOURCE.LL3. It looks like maybe
they skip writing to the file if you had scored 0 (leading to 0-1 = 65535 in 16-bit unsigned
arithmetic)? That’s interesting:
lsl local2
ldi 1
sub
sag global124
pushi 2
lofsa {RESOURCE.LL3}
push
pushi 2
callk FOpen, 4
sat temp2
push
ldi 65535
ne?
bnt code_068f
pushi 4
lea @temp3
push
pushi 140
pushi 12
lsg global124
callk Format, 8
pushi 2
lst temp2
lea @temp3
push
callk FPuts, 4
code_068f:
pushi 1
lst temp2
callk FClose, 2
Still looking for local2 references, I find the part of the code which checks your answer.
Being disassembly rather than a decompilation, it’s rather long, so I’ll summarize first:
if (local5 == local6) {
// right answer
say "Correct" (message 9)
play "Correct" music
increase local2 (right answer count)
increase local3 (which picture to show)
} else {
// wrong answer
say "Wrong" (message 10)
play "Wrong" music
decrease local3 if it's not 0
}
show the new picture
(she has fewer clothes the higher local3 gets)
… and here’s the bytecode for all that:
lsl local5
lal local6
eq?
bnt code_055b
pushi 2
lsl local5
pushi 2
call localproc_0754, 4
pushi #number
pushi 1
pushi 140
pushi 6
pushi 1
pushi 1
pushi 42
pushi 0
lag gTheMusic
send 16
pushi 8
pushi 140
pushi 9
pushi 67
pushi 190
pushi 8
pushi 25
pushi 3
pushi 88
calle proc255_0, 16
+al local2
+al local3
jmp code_0594
code_055b:
pushi 2
lsl local5
pushi 4
call localproc_0754, 4
pushi #number
pushi 1
pushi 141
pushi 6
pushi 1
pushi 1
pushi 42
pushi 0
lag gTheMusic
send 16
pushi 8
pushi 140
pushi 10
pushi 67
pushi 190
pushi 8
pushi 25
pushi 3
pushi 88
calle proc255_0, 16
lal local3
bnt code_0594
-al local3
code_0594:
pushi #setCel
pushi 1
lsl local3
pushi 198
pushi 0
lofsa aSuit
send 10
ldi 3
aTop seconds
Now to Patch It
So, having learned everything we need to know, I plan to patch that last code snippet such that:
- it still tells me if I’m correct or not
- the accounting in local2 and local3 will adjust as if I were correct every time
That means just changing the lal local3; bnt 0594; -al local3 sequence into
a +al local2; +al local3 like the correct path had. I get SCI Companion to give me
the raw disassembly with the bytecodes next to it, so I know what byte sequence to copy. And,
thankfully, there is enough room to avoid changing the size of the overall code.

I had 3 bytes left to fill with some kind of no-op, so I tried 32 00 00 (an unconditional
jump of 0 bytes)… and hoped for the best! ScummVM did not choke on it, and neither did
DOSBox when running the actual Sierra interpreter, so I think I’m in the clear.
More importantly, it worked! I answered every question wrong, but the clothes kept coming off the picture on the left, and then it told me I could play at the most adult level:

The Patch
Just put this script.140 patch as script.140 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 answers.