‘Round these parts, we write about old Sierra games and their rich inner lives. As I’m often at pains to point out, this is thanks to the brilliant script decompiler written by Phil Fortier for SCI Companion. Released in 2015, it was the first and only decompiler for SCI games — at least as far as the world is concerned. And now lo, for there is another.
Last year, I had a vision and began writing my own decompiler — a mass decompiler — with the goal of wiring it up to my script tools for annotations. Annotations are comments and symbols that transform decompiled code from something you can read into something you want to. That’s how I learned the scripts in the first place: by writing automatic annotators and reading the results. I wanted to share this with the community* but the particulars of SCI Companion made it a thorny problem. The decompiler I envisioned could unlock the solution, but I didn’t know how to write it. I wasn’t sure I ever would. The only certainty was that win or lose, it would take a while.
In the meantime, I slowly obtained as many games and variants as I could. What’s a mass decompiler without the masses? There are only about sixty games, but they were heavily revised, ported, and translated. Software scavenger hunts are fun and this one as been successful. I’ve now amassed over three hundred versions of SCI games from 1988 through 1996. While that’s not every single one, you have my permission to say it is.
Today, with one command and a couple of cores, I’ve decompiled and annotated every Sierra SCI game, and practically every version, and dumped the results on github for everyone to enjoy. Gentlemen… BEHOLD!
https://github.com/sluicebox/sci-scripts
You’re still here?? Look, you’re welcome to stay, but I just linked to half a gig of way more interesting text. I even got out the big font! (When do we ever get out the big font?) In fact, I’m counting on the crowd thinning out so I can indulge in some inside baseball.
I just want to kick back and tell the story of how this came to be. We’ll see where Sierra’s script language came from, what reverse engineers have done with it, and why I’m cheerfully undermining the blog with today’s release. I’ve got a lot of meta-rules to break. You go outside and play with your scripts!
When I talk about Sierra code, I break it into three categories:
-
Game Scripts: This is the unique code that defines a game. Every room in every game gets its own script. You care about this if you want to solve murder mysteries or find easter eggs. This is probably the only code you care about.
-
System Scripts: These are the supporting scripts that appear in every game. They form a common runtime library that the games are built on. You’ll find generic classes for rooms and actors and icon bars, and utility functions for things like message boxes and math. Even the game loop lives here. As you get deeper into SCI mechanics, you care more about these scripts, although perhaps reluctantly.
-
The Interpreter: This is the program that runs the show; you know it as SIERRA.EXE or SCIV.EXE. The interpreter was written in C and a lot of assembly, and then rewritten in C++ and slightly less assembly. It loads drivers, decodes resources, and runs the first game script in a virtual machine. It’s the “VM” in ScummVM. From there, it just follows orders until a script sets the quit flag or it famously crashes. It also contains over a hundred kernel functions that scripts call to do work. You care about the interpreter if you want to solve bonus mysteries or find timebombs. Or if you’re crazy enough to replace the whole thing.
Today is all about the scripts. Let’s see what one looks like! Remember that Sierra programmers wrote these in their proprietary language (also called Script) and compiled them with their in-house compiler to SCI bytecode. Those are the bytes that shipped with the games. Decompiling can never recover the original text. Symbols are lost. Control flow is ambiguous. Compilers have bugs. Optimizations ruin everything.
But God is alive, and Magic is afoot.
(instance mints of View (method (doVerb param1) (switch param1 (5 (if (< global153 3) (if (not (global0 has: 23)) (global2 setScript: takeMintScr) else (global91 say: noun param1 35) ) else (global91 say: 7 5 32) ) ) (1 (if (< global153 3) (global91 say: noun param1 33) else (global91 say: noun param1 32) ) ) (else (super doVerb: param1 &rest) ) ) ) )
Thanks, decompiler! Now let’s see it with annotations.
(instance mints of View (method (doVerb theVerb) (switch theVerb (5 (if (< gAct 3) (if (not (gEgo has: 23)) (gCurRoom setScript: takeMintScr) else (gMessager say: noun theVerb 35) ) else (gMessager say: 7 5 32) ) ) (1 (if (< gAct 3) (gMessager say: noun theVerb 33) else (gMessager say: noun theVerb 32) ) ) (else (super doVerb: theVerb &rest) ) ) ) )
This is the code that runs when you click the mint dish in King’s Quest VI. And thanks to the annotations, you know what it does. Each comment was generated by an annotator. The message annotator is usually the most helpful. Without the comments, you’re just staring at numbers. The global variables were renamed by two annotators: one that handles system globals and another that knows KQ6 details. As you can see in the first version, some symbols come straight from the game. Sierra generously included them for debugging. Combine those names with annotations and you get highly readable code.
Annotations aside, scope out that language. SCI Script is often described as LISP-like, but that’s just a curvy stereotype. It looks like LISP because of parenthesis and prefix notation, but if that’s all it takes… well please tell that to a LISP programmer. They deserve it. This language doesn’t even have LISts! The syntax does make it easy to parse, but I haven’t seen anyone take advantage of that; except compiler authors and me. So join the rest of the world and forget about LISP. The real inspiration for SCI Script is Smalltalk.
Jeff Stephenson is the father of SCI — he wrote the language, the compiler, and the bytecode interpreter. Two years ago, the Video Game Newsroom Time Machine scored a two hour interview about his life and career, and he recounted his influences:
Somewhere in there, BYTE Magazine came out with their Smalltalk issue and I discovered object oriented programming, and you know, I read that issue cover to cover I think, and sometimes multiple times maybe. […]
In any case I started learning about object oriented programming and it just really resonated with me. And then suddenly we were able to start displaying more than 16 colors on monitors, and Ken wanted of course to take advantage of that, but AGI was written in such a way that it was going to take a major rework of the entire game engine and language and everything in order to support 256 colors. And so that’s when I pitched Ken on SCI and basically saying okay let’s go with a whole new language, we’re going to have to rewrite this thing anyway, let’s make things better. And he was pretty dubious, but I guess he figured since we were having to rewrite everything anyway, he might as well let me do it.
BYTE Magazine dedicated one issue to a language each year. In August 1981, that was Smalltalk. Reading through, I was first struck by the magazine cover. Oh… it has a back story. It’s a charming retort to the Pascal cover from 1978 that painted Smalltalk as aloof and inaccessible. I love it; did that allegorical slight really fester at Xerox PARC for three years? Of course it did! They’re nerds! And their response? A textbook clapback from the Yacht Rock era.
Reading further, I was surprised by how much terminology made its way into SCI: selectors, method dictionaries, temporary variables, receivers — they’re all in those pages. Even SCI’s ubiquitous doit method is a Smalltalk convention. The influence is clear.
Jeff also mentioned Objective C, and I’m sure that contributed too, but I refused to research it. Sorry, it’s a personal prejudice. That language is just so damned ugly that, like a filthy freakin’ opossum, it triggers my fight-or-flight. And I’m done breaking laptops! So we’re sticking with the Smalltalk narrative. And breaking meta-rules instead.
My one exposure to Smalltalk was in school. The assignment was to implement the Enigma cipher in a language you didn’t know. For extra credit, you could write a program to crack it. Excuse me? Breaking Nazi encryption is optional?? Not in my family! We really need Grandpa Benshoof to survive D-Day! Smalltalk did the trick and I remember it fondly. My fascist decoder worked, but as the messages got longer it got slower. Really slow. Even on the expensive machines. Oh well, I wasn’t getting graded on speed. Later, the department chair left a handwritten note about my impressive use of CPU cycles. The polite implication was that I would have lost us the war for want of a hash table.
Speaking of impressions! I’m impressed with the shelf life on that Smalltalk issue. SCI was developed in 1988 and yet these technical articles from 1981 were still relevant. In a way, they’re timeless. Just not timely.
When Can I Buy It?
There are currently no personal computer implementations for the Smalltalk-80
language. Because of this, I’m sure we’ll be criticized by some for introducing
the language too early and frustrating our readers. Nevertheless, I feel that
the time to begin exposing people to object-oriented language is now. Only by challenging and enticing the personal computer community can we stimulate the industry to create the machines we all dream of.
Smalltalk fans had the programming language, but not the software. SCI fans had the opposite problem. They had years of games, and years to reverse engineer them, but the source language was a secret. How do you decompile that? W