Leave a comment

Snail Trek

I have released a series of four short episodic games in the same style as my main project (Cascade Quest). The games are called Snail Trek, and are available on Steam. Follow the story of a crew of intrepid snails as they search for a new home world!

These games show off the parser-based retro game framework I’ve developed. Some of the technical stuff:

  • the parser has auto-suggest and auto-correct
  • the parser is context sensitive to the player’s current location
  • no puzzle dead ends
  • autosaves
  • still lots of Sierra-style deaths!

Please go check them out!

SS_0002_Layer 7.jpg


Leave a comment

Speech recognition for adventure games

On linkedin, Someone posted a link to an example of Unity’s speech recognition API for Windows 10. It sounded simple to set up, so I decided to try it out. I’d done some basic research a while back to see if speech input might be an decent alternative to the text parser input in Cascade Quest.

With Unity 5.5 and Windows 10, it was just a matter of minutes before I had something very basic working.

With the Unity APIs, there are basically three ways to configure speech input:

  • A dictation recognizer, which can recognize general phrases. This requires internet connectivity though, and so it probably not suitable for the quick responses needed for a game.
  • A keyword recognizer, which simply recognizes single words (or series of words) from a fixed list. This is also not very useful for Cascade Quest, since I need to be able to recognize natural language, like the text parser can.
  • A grammar recognizer, which is provided a list of grammar rules to base its output on. This is really the only viable solution for me.

Unfortunately the grammar needs to be in the form of an SRGS XML file. This isn’t ideal, since I’m constructing the grammar (including the words to be used) from data available at runtime.

There were two main challenges to overcome:

  1. Turning the actual grammar rules into SRGS.
  2. “Cleaning” the word list so it can be used in the grammar.

The grammar

The form the text parser grammar was in was challenging to convert to SRGS. To add the problem, there is no way to debug issues with a broken grammar.

The API takes an xml file, loads it and then either works or doesn’t. It gives no indication if the SRGS is invalid, or if something just isn’t recognized. There are no errors or status (other than “everything is ok, I’m running”). On top of that, if a grammar is loaded that is invalid, all future attempts with a correctly-functioning grammar will also fail to work (until Unity is closed and restarted). I don’t know if this is a problem with the underlying Windows APIs or how Unity uses them. Nevertheless, it made it extremely tedious and (until I figured out what was going on) confusing to debug.

In the end, I ended up having to hand-code some reasonable grammar, increasing the complexity bit by bit and always testing it still worked.

The words

The next issue is the words- or specifically, the transformations of the words (pluralizing, adding -ing or -ed, etc…). My game has rules for modifying the suffixes of words, but they work from completed text input back to a known word. For example, postmen is converted to postman, which is a known word. Likewise, wolves would be converted to wolf. We check the suffix of the word, and if it is a known plural suffix, we convert it to the singular form and validate that it is a known word.

The speech recognizer grammar needs to include all variations of a word, but that means going in the other direction: from the singular to the plural (or root to transformed). For “wolf”, we would generate a number of options: wolves, wolfs, wolfes. All these are valid transformations based on our suffix rules. But not all of them are real words. So to validate these transformations, we need to check against a master English word list. I found one online that contained about 500,000 words (including plurals, verb tenses, and such).

The result

The end result is something that works “ok”. I’m sure it would be a lot more accurate if I could limit the grammar only to words that are included in the current loaded room (or at least weight those words more highly). I could do that, but I would need a different SRGS XML file for each room in the game. Even that isn’t a great solution though, because other pieces of logic in the game (which respond to text parser input) might be loaded or unloaded dynamically.

Anyway, speech recognition as an input method for Cascade Quest is something I’ll keep in my back pocket as a possibility.

How does it actually feel to play? “Ok”. I found it got tiring speaking to the game for very long. Would anyone actually use it? If I get it into a more reliable state, maybe I’ll do some playtesting to find out.


Adventure game puzzle design

By “adventure game”, I really mean any story-based game.

This is post is mainly just a dump of useful links regarding puzzle design, so I can have them all in one place. There won’t be anything terribly elucidating here, just links to useful articles.

I think there are some more, but I’ve lost them.

Right now I’m trying to apply this kind of puzzle theory more rigorously to Cascade Quest. Many puzzles in their current form in the game are woefully unsatisfactory, as has been demonstrated by some playtesting.

Right now I’m trying to polish up the puzzles in the first zone of the game. One thing I’m struggling with is trying to make the puzzle tree more “bushy”. What that boils down to (if you read some of the articles listed above), is trying to give the player several things to do at any particular time. A strictly linear puzzle progression can lead to player frustration if they can’t solve the current puzzle they’re working on, and have nothing else to do.

I’ve managed to make many of the puzzles have multiple independent conditions that need to be met. However, I’m running into problems informing the player of the necessary conditions. Usually there is one obvious thing the player needs to do to solve a puzzle. When they accomplish that, they may only then find that they need something additional. The end result is that the player will probably still progress linearly through the game (and possibly get blocked).

This is more of a narrative problem, I suppose. The puzzle dependency graph may be “bushy”, but the in-game narrative still drives the player through a linear discovery. I haven’t seen much discussion of this in any of the articles I linked, but it’s become a problem with nearly every puzzle to which I’ve added multiple pre-conditions.

One good example of this kind of being glossed over are the GDC slides I linked above. One example they give for “bushifying” the puzzle tree involves opening a chest. You need a key to do so. To add an additional pre-condition, we can say that the chest has rusty hinges, and so you also need a can of oil. The player now has two things to do to occupy their time.

However, how do you deliver that narrative? The player won’t realize the chest has rusty stuck hinges unless they already have the key and have tried to open the chest. So this attempt at parallelizing the puzzle tree risks becoming simply a longer linear chain in the tree.

So these are the kinds of things I’m thinking about right now.




Leave a comment

Deeply-nested coroutines in Unity

In Unity, coroutines are essentially methods that execute across several frames. They are, in a sense, some syntactic sugar that lets you avoid having to keep track of the state of a sequence of operations (for instance, fading from one color to another) in member variables of a behavior. Instead, all state can be method-local. Refer to the Unity documentation for the basics around coroutines.

For a recent project (A Unity “plugin” that runs old Sierra games – or at least those created with my SCI Companion), I needed to have an interpreter running that processes byte code – basically a game engine within a game engine. In its original (non-Unity) form, I ran the interpreter on a separate thread. This simplified things in some sense, as I could pause and continue this thread in order to pause or continue the interpreter (e.g. for stepping through byte code instructions one by one). In addition, the actual callstack of this thread could be used to store the actual callstack of the interpreter. The interpreter doesn’t only process byte-code – it can call through to “kernel” functions that I implement. And those in turn can call back into byte-code.

Supporting something like this on the same thread on which the “game engine within a game” is running would be extremely difficult, as control needs to return from the Update part of the game loop on each frame (for something like a standard Windows application, this wouldn’t be as difficult, as we can pump messages and process input at any point).

When I ported this project to Unity, I kept this architecture. However, WebGL was one of my target platforms – and javascript/html5 doesn’t support threads (currently). Indeed, building my project for WebGL verified this.

So I was left with the task of figuring out how to switch my architecture over to using coroutines – or figuring out if it was even possible! Remember, the callstack in my interpreter can be arbitrarily deep, and I really didn’t want to make every function coroutine aware.

The remainder of this post will summarize how I managed to accomplish this.


I need the following things:

  • Some of my interpreter’s kernel functions need to yield (return control to Unity’s update loop, as they pause indefinitely).
  • Some of them need to yield conditionally (only return control sometimes).
  • My individual byte-code instructions need to conditionally yield also, since they may call into kernel functions.
  • If my in-game debugger is active, then of course I need to be able to potentially yield on each instruction processed.

Here’s the plan I came up with. First:

There is only a single coroutine – a top level “RunInterpreter” function that returns an IEnumerator.

It, in turn, calls into the rest of my interpreter code (specifically, it is a loop that processes byte code instructions). All other functions that either return control – or call into other functions that return control – need to return IEnumerable (not IEnumerator). Yes, this does mean that pretty much everything in my interpreter needs to be “coroutine aware”. That ended up not being a huge deal for the most part though. The trickiest bit was deciding how to return values from functions now that they must return IEnumerable.

For functions that clearly need to yield control (such as the Wait kernel, which waits for a specified number of real world milliseconds), or when the in-game debugger is broken into the interpreter, we simply need to do:

yield return null;

Now, I also had a situation where a virtual function was called. Some overrides needed to yield, and some didn’t. Because of the potential need to yield, the virtual function signature had to have a return type of IEnumerable. So what about those overrides that should not yield? A function that returns IEnumerable in C# won’t compile unless there is a yield somewhere in it. The solution is to use yield break:

// Pushes a value onto the stack
class push : Instruction
public override IEnumerable Do(byte opcode)
    yield break; // Don't yield at all!
public override byte Opcode { get { return 0x36; } }

This indicates that the enumeration has terminated – so basically the function will just return an empty enumerable. This is actually what happens at the end of a IEnumerable function which doesn’t end with a yield – there’s basically an implicit yield break there. From this, we can gather that in any cases where you had an early return from a function, yield break is also what you should use.

Now what about functions that call into other functions that might yield (i.e. other functions that return IEnumerable). For instance, in my project there is a callk byte-code instruction that calls a kernel function. A kernel function (such as Wait) might yield, so that needs to be propagated out. In that scenario, I iterate over the returned IEnumerable and yield each element:

foreach (var guy in interpreter.Kernel.Invoke(index, numParams, context))
yield return guy;

Note that in the case where the kernel function didn’t yield at all (which is the majority of the cases), an empty enumerable is returned. This means yield return guy is never hit, and we won’t yield control at this point.

This is important, as we definitely don’t want to accidentally yield control. Doing so would suddenly introduce a 16ms (or whatever your fixed timestep is) wait before we continued execution of the interpreter.

That’s pretty much it. Once you get the hang of how yield works, it ends up being pretty straightforward.


Leave a comment

Foreshift: Ludum Dare #35 post-mortem

Last weekend I completed the Ludum Dare 48 hour competition. The goal is to make a game from scratch in 48 hours: all the coding (apart from frameworks you make public beforehand), art and audio need to be done from scratch and by one person. It takes place around the world and well over one thousand people submit entries.

You can play my entry on the web if you have an html5 compatible browser.

The Ludum Dare competition entry page is here.

I’ve only completed this game jam once before (a few years ago), but have attempted it several times. I usually end up giving up partway through when I have no good ideas, my ideas aren’t panning out well enough, or it stops being fun.



Title screen sequence


I thought that was going to happen again this time, because as of Saturday morning (the compo goes from 6pm Friday to 6pm Sunday in my timezone), I had rejected my initial idea and was back to square one.

The theme for this jam (announced Friday at 6pm) was Shapeshift. Instead of trying to get creative with the theme, I originally decided to just do the obvious: the player is an object that can morph into other shapes. In particular, you could morph between a circle, square and triangle, and move through the world in different ways depending on that. Movement was accomplished via torque (rolling). Not terribly original, and when I got a prototype up and running I didn’t find the mechanics very fun. In addition, the puzzles I was creating were very hard to fine tune.

At around noon on Saturday, I got a better idea: you would instead move around the levels like a normal character, and you would be able to swap the shapes of objects in the scene. A key difference here is that not all the shapes can move. A problem with my original concept is that the triangle and square pretty much had to move (in order to accomplish anything while playing them). This isn’t a natural thing for a square or triangle to do. With the new concept, movement is generally accomplished by turning an object into a circle. Squares and triangles are used for different tactics.

A constraint to make things more interesting (by limiting your options) is that you may only swap a shape with another shape that you are “holding”.

I was able to salvage some of the existing work I’d done on my first prototype and quickly get something up and running that seemed like it could be fun.

From here on out, I’ll discuss how I approached making the art, sounds and levels.


Nearly all the art for my game was scanned hand drawings or heavily processed bits and pieces from photographs I had taken.

Thought bubbles

Sometimes little pieces of “final detail” can inspire you when uncertain game mechanics can not. When I was pondering how to show the UI for the “held shape” the player has, I thought of some of the UI in Little Big Planet – in particular the menu selections that popup on in-world billboards that are attached to the player by a rope.

So I decided that the held shape should be visible in a thought bubble that follows the player around in a nice organic way. My motivation had been lacking, but suddenly this seemed like a fun little challenge to try to implement, even if it wasn’t a core gameplay mechanic.




The small mini though bubbles coming out of the player’s head could be attached on virtual hinges to the main thought bubble. I’d never used hinge joints in Unity before, but it was fairly straightforward to set up. The tricky part was setting the rigid body properties (mass, drag, etc…) to make the thought bubble in a reasonable fashion. Early on sometimes it would become disconnected and fly away, or continue bouncing uncontrollably.

A thought bubble with the held shape as the thought. The blue dots are the hinge joints.

A thought bubble with the held shape as the thought. The blue dots are the hinge joints.

The balloons and the held shape images are all just scanned hand drawings.


I took some nice mossy photos the previous weekend, and so I thought I would chop pieces out of them in order to construct platforms.

All art needs to be created in the 48 hour time frame of the competition, but there is a grey area when it comes to “derivative” works of art. It’s probably ok if you create something (during the 48 hours) that is partially based on previously existing art, or heavily processed parts of that art – as long as you’re creating something new.

I extracted bits from the blob of moss on the left to create the platforms.

I extracted bits from the blob of moss on the left to create the platforms.

At this point I decided that I should incorporate some semblance of lighting into the game. I pull out long thin sections of moss and used the burn and dodge tools in Photoshop to create the effect of light on the platforms.

Instead of having just a single strip of moss (and variations of) to use in the game, I created variations for different platform orientations: horizontal, vertical and two diagonals. Since I was “baking” the lighting right into the platforms, they can’t be rotated arbitrarily in game – the lighting would look wrong. So making the variations was a simple thing that went a long way to make the lighting look somewhat polished:


Horizontals on the top, 2 verticals on the left, and 2 diagonals to the right of the verticals (rotated so they fit nicely in the spritesheet)

Horizontals on the top, 2 verticals on the left, and 2 diagonals to the right of the verticals (rotated so they fit nicely in the spritesheet)


The platforms in game:


Semi-consistent lighting in-game (from the top right) regardless of platform orientation.

Semi-consistent lighting in-game (from the top right) regardless of platform orientation.


The shapes

I had hand-drawn shapes for the UI versions of the three shapes, but I needed something to represent them in game. Bare wood seemed to fit with the forest theme, so I grabbed some parts of tree trunks from a photo and cut them into the appropriate shapes.


Circle, square and triangle shapes, along with "glowing" versions. The black dots are something I do so that I can have stable sprite names when I auto-slice the spritesheet in Unity before I've filled in all the parts of the spritesheet.

Circle, square and triangle shapes, along with “glowing” versions. (The black dots are something I do so that I can have stable sprite names when I auto-slice the spritesheet in Unity before I’ve filled in all the parts of the spritesheet).


I probably could have chosen a better source image, because they don’t exactly look like wood (but they are!). Later on, I decided I wanted a glow-y hover effect on the shapes, so I added versions of them with glow (typically easier and cheaper than doing glow programatically).

Now, since the shapes can rotate in-game, I needed some kind of dynamic lighting (hence the flatness of the source texture – no lighting baked in). I felt this was a pretty important aspect of the game, so I did my duty and implemented a 2d lighting shader that used normal maps:


Normal map for the shapes

Normal map for the shapes


And how they look in-game:




I’m not terribly satisfied with the final look (I should have used a more representative wood image), but the extra effort in implementing the custom shader was worth it.


The character

Character animation is hard (for me). I didn’t think I would be able to come up with a good-looking walk cycle, let alone even a static sprite/model that fit in with the forest scene. So I decided to think outside of the box a bit.

I took a drawing course a few years back, and I remember a lot of my drawings having kind of a scratchy, messy ethereal look. I decided it wouldn’t be hard to make some scratches that looked like a humanoid form. Better yet, I could leverage a walking cycle for a stick figure to help me draw the right forms.

Using that (and my iPad as a light table to help with tracing), I was able to draw this kind of stuff:



I scanned it in, adjusted light levels and other assorted processing,  assembled the parts into a spritesheet and imported it into Unity and generated a 2d animation:


Hand-drawn walk cycle

Hand-drawn walk cycle


For the jump and idle states, I just did 2-frame animations to save time. If I’d had more time I would have make separate walking and running animations too.

Doors and switches

Does this look familiar?


Shelf fungus was used for the doors and switches.

Shelf fungus was used for the doors and switches.


If you’ve played the game, you may have noticed that the fungus in that picture looks a lot like the doors and switches:




Again, these were processed in Photoshop to make the lighting consistent with their orientations in-game.

I wanted to have the door incorporated into some structure that make it feel more like a door, but I didn’t have time. I also struggled a bit with the physics here, and I bet I have some bugs because of this (the door can come down on top of the shapes and push them out of the way).


Door and switch

Door and switch


Shape spawners

The final game mechanic didn’t get implemented until mid-way through the second day. As I was designing levels I realized it was frustrating to keep having to reset the entire level when a shape ended up rolling off to somewhere where it could no longer be used. There’s generally no way to move a shape upward (something I would fix if I had time to implement more mechanics, maybe).

I can associate a shape with an optional spawner. Then when the shape “dies” (when it rolls off the screen), it will get respawned at its original position.

In general though, this behavior isn’t very well thought out. It doesn’t avoid the need to reset a level – a shape can still end up in a “dead end” without dying. And there are some subtle issues that arise when a shape has been “shifted” before it dies. What shape should it respawn as? I have to take the “held shape” into consideration. I attempt to keep the shape distribution even (as that’s a puzzle constraint), but it’s not always possible to do that. So there are some flaws here.

At any rate, this is about art. The shape spawner looks like a tree. It’s source image is a rock with moss on it (turned purpleish, for the bush part), and a real tree trunk for the trunk. Originally I was going to go for some kind of cannon, but I failed at drawing that. So instead I figured shapes could drop out of a tree.


The spawning bush.

The spawning bush.


The original patch of moss used for the above:





The bottom of the screen is lined with spikes that kill the player or the shapes. Where do they come from? A photo I took of a Devil’s Club plant, which has a very spiny stalk:



The texture I created from this that is used in game:




Dust motes

What forest would be complete without bits of dust and pollen floating around? Ideally I’d have some sunshafts and dappled light flickering on things, but hey, this is 48 hours.

The dust motes were simply a little blob texture created in Photoshop. I have a script in Unity that creates a number of these and sends them off in random directions. They fade in, move around for a bit, then fade out. Maybe 20 minutes or so of work to make, and they help a lot with the atmosphere:



The title sequence

A good title screen is important to set expectations of quality and polish. I stopped designing levels with 2 hours left in the competition, and devoted that remaining 2 hours to the title and ending screens.

For the title, I did what I had been doing all along – which was draw some stuff on paper and scan it in. Scratchy letters to go along with the theme (I actually used no fonts in the game at all!).




When I did this, I realized that the “I” in Foreshift (a portmanteau of forest and shift) looked a lot like the character idle animation. So I left it out of the texture and just plopped the character there in game. Now my title would be dynamic! He (or she) is standing on an invisible platform which disappears when you press any key. That causes the character to drop down (transitioning to a jump animation state) and land on a platform, whereupon I direct him/her to the right. As you saw at the beginning of this post:





I like composing music (though I’m not very good at it), but I find it extremely time-consuming. As a result, I used no music in the game at all. I was going to try to record a few chord progressions on my keyboard for “winning a level”, but I ended up not having time at the end.

However, I did put a lot of effort into sound effects. I’ll describe what I ended up using for various effects.

The ambient background noise

The airy ambient noise is just a recording from my apartment balcony. Unfortunately the birds had stopped chirping by the time I got around to recording it, so I add to add bird sounds manually.

I used sfxr to generate bird sounds. Mostly just by clicking “random” until it generated a sound that roughly approximated a chirp. I then added these to the background ambient noise in my audio editor.




Character sounds

The walking sound is me stomping on a shag carpet:



The sound the player makes when jumping used to be more of a grunt. When I finalized the look of the character, I decided I needed something more ethereal and softer. So I recorded a bunch of “huh” sounds. I recorded four variations of this:

Shape sounds

When a shape impacts something with enough velocity (either a platform or another shape), it makes a thud. This is me slapping my hand on a leather sofa.



The pop sound when you switch shapes is just me doing a mouth pop.



The circle shape makes a sound when it rolls. I’ve used a salad spinner to make rolling sounds before, but that makes more sense for a hard surface. I tried to imagine what rolling a bowling ball on the forest floor would sound like. I thought maybe leaf crinkles? I had no leaves on hand, and no time to go outside to record something, so I ended up just crumpling up a plastic bag.



Other sounds

The door opening and closing is just a drawer opening and closing. Likewise, the “win the level” sound is just a me opening a door:


The death sound (I think, I forget) is a combination of plastic bag crunching and slapping the leather couch:



What went right

I’m a lot more familiar with Unity now that I’ve been using it consistently for several months. This made it easy to get stuff up and running quickly.

I got a good amount of sleep (7 hours the first night, 4 hours the second night), so I never felt like I was running on empty. I’m not sure I could do a 3-day jam though.

I think I paced myself pretty well. I made it a goal of finishing the level design two hours before the end of the compo just to ensure I’d have enough time to put some finishing touches in. I did roughly that, and in the final hour and a half I made the finishing touches I needed:

  • Title screen – first impressions are important, so I wanted to do this well.
  • Some kind of ending when you finish the last level (just a credits screen and a button that sends you back to the start – but it’s better than nothing).
  • A refresh button that resets the level incase you get into an impossible-to-solve situation

I also made it a goal of prioritizing some of the polish before the level design, and I think that was a good idea. Most people who play/judge probably won’t get through all 7 levels. So from that perspective, it’s more important to make the beginning a smooth experience. Some examples of that are:

  • Making sure the introductory levels are clear and simple
  • Making the death and respawn a good experience. Too many jam games just have the player vanish without flair and the level gets instantly reset. This makes the game feel cheap and unprofessional. Once I realized that the player dying was going to be a thing, I put work into it: sound effects, and a dying animation. I did a similar thing for the shapes “dying” too, but not quite as well.
  • I even made a skull and crossbones appear in the player’s thought balloon when they die, and the thought balloon drifts off into space.


Death sequence

Death sequence


For the art, I think I did a good job choosing goals that were within my scope: Which was either pieces of photographs that were manipulated to give lighting, or “intentionally rough” hand drawn scanned sketches.

I’m not 100% pleased with the consistency of the art (for instance, there is a bit of a confusing dichotomy between the scratchy line art and the other stuff), but it’s not bad. I definitely took some time to make sure all the visuals fit nicely together. The forested background is probably one piece of art I’m not very pleased with (The exit door and the switch/door combo also look a bit unfinished).

During the 48 hours, I saw a lot of people (on twitter) putting up links to preliminary builds, short videos and other things. While it’s nice to keep the community updated on what you’re doing (to help inspire and posh others, say), I didn’t think that would be a good use of my time. I put up maybe one screenshot, but that’s about it. I didn’t prepare any builds for playtesting, or make any videos.

What could have gone better

Random technical issues

I did have some technical problems. I left audio until mid-way through the second day of competition, only to discover that my editing software (Sony Vegas) had suddenly started crashing on startup. I spent half an hour fixing this (finally tracking it down to a codec installed on my machine, and renaming the .dll to something else so Vegas couldn’t find it).

Test out all your tools beforehand!


I still don’t trust Unity’s WebGL build completely. What it does is super impressive, and it ended up working out fine in the end. Before the compo started, I tested out the workflow of making an html5 build and uploading it to my webserver (icefallgames.com), and that worked without issue (I was surprised!).

Chrome was flakey in running the html5 builds locally (it worked 50% of the time, maybe 75% of the time when refreshing the webpage). So I often had to upload it to my server to know if there was really an issue with the build or not.

Right at the end, I made an html5 build with a different default resolution (so that  could embed it in the competition entry page), and suddenly my main character’s texture was all messed up! I struggled with this for a while, but clearing out all the build directories and restarting Unity seemed to fix the problem. Not really sure what was going on.

Physics gameplay

When designing levels, fine-tuning the physics was more difficult than I had anticipated. I haven’t done many physics-based games. Tweak one parameter to fix a certain situation, and you break other places. This made the final push for level design take longer than I would have liked.

The jumping is also a bit buggy currently. The player sometimes catches on platform edges (you can always get out of it, but it doesn’t look good). This is one of the first platform games I’ve made, and jumping and movement is notoriously hard to get right for platformers.

Unforeseen gameplay flaws

After completing 6 of my levels, I realized there was a fundamental flaw in the gameplay. I describe this a bit in the art section about the shape spawners. In the end, it doesn’t really matter because you can always just reset the level. But it is possible that it might make the level easier to complete, depending what happens.

It was also evident with playtesting that it was very easy to get the level into an unsolvable situation. Again, the reset button (or player suicide) just resets the level, so at least I have that as an escape valve. But if this were a “real” game, I would need to address this. I’m not sure this should be listed in “what went wrong”, because I’m not sure it’s avoidable when designing a game in such a short time.


There were a few bits of polish on my list. I wanted a better “winning the level” experience (some flourish and/or music). And I wanted to juice things up with some screen shake or other effects. I really wanted to, but decided it was too risky with only 15 minutes left (which is when I got to that work item).

It also would have been nice to have time to make the levels a little more visually distinct.


Ok, I guess that’s about it! Please try my game and let me know what you think!



Decompiling SCI – part 4 – final steps

Here’s a link to part 1 of this series.

Generating the abstract syntax tree

Generating the AST from the instruction node tree ends up being fairly straightforward.

SCI Companion has the following syntax nodes (that appear in the AST): value (these can be tokens, strings, saids, selectors or numbers), complex value (like value, but allows for an indexer if it’s a token), assignment, variable declaration, define, class property, function, class definition, synonym, code block, send param, L-value, send call, procedure call, condition expression (old syntax only), case, switch, asm statement, asm block, return, binary operation, unary operation, n-ary operation, for loop, while loop, do loop, break statement, continue statement, rest statement, script, comment, function parameter, function signature, if, export, cond statement.

For most of the control structures in the tree, there ends up being a straight mapping to a particular type of syntax node.

For sequences of raw instructions (that don’t affect control flow), it becomes just slightly more involved:

ldi, pushi, push0, push1, push2

These end up simply being numeric values:

	ldi 3 
	aTop cycles

	(= cycles 3)

callk, callb, calle, call

These become procedure calls:

	pushi 3
	callk Random 4

	(Random 0 3)

send, self, super

These are a little more involved, since they may have multiple send params for a single send target. Each one has a parameter count associated with it, and we need to assume that we can get a numeric value for the instruction that designates the parameter count.

	pushi 28 // $28 number
	pushi 96 // 150
	pushi 3 // $3 loop
	pushi ff // -1
	pushi 27 // $27 play
	lag gGlobalSound 
	send 12 

	(gGlobalSound number: 150 loop: -1 play: self)

lsub, mul, div, mod, shr, shl, xor, and, or, add, eq, gt, lt, le, ne, ge, ugt, uge, ult, ule

These become binary operations:

	pTos state 
	ldi 2 

	(+ state 2)

bnot, not, neg

These become unary operations:

	lal local1 

	(not local1)


Simply a rest statement:

	pushi 6e // $6e init
	&rest 1 
	super KQ6Room 4 

	(super init: &rest)


Becomes a value that is marked as being a pointer (and possibly has an indexer):

	lea local13


class, pushself

Become values that are marked as tokens:

	pushi 51 // $51 delete
	lag gKq6WalkHandler 
	send 6 

	(gKq6WalkHandler delete: self)

lofsa, lofss

Become values that are marked as literal strings, saids, or tokens depending on the numeric value they reference (we need to reference the script resource to find out):

	lofss $0644 // *** ... well, Okay.
	lofss $0542 // lampStartScript
	calle 399 procedure_0000 3 // proc921_0 

	(proc921_0 {*** ... well, Okay} lampStartScript)

atop, stop

These become assignment operations. We need to reference the script resource here to look up the property name, since these instructions use a property index which pertains to the “current” object.

	lap param1 
	aTop state 

	(= state param1)

ptos, ptoa

Instructions to read from class properties. Similar to above in that we need to look up the property name, but these are simply values marked as tokens.

	pTos state 
	ldi 5 

	(> state 5)

iptoa, dptoa, iptos, dptos

Similar to the above, but this ends up being a unary operation (– or ++):

	dpToa state 

	(-- state)


Becomes a return statement.


Becomes a property value for a “self” token (selfID puts a pointer to self in the accumulator, while pushSelf puts it on the stack):

	sal local8

	(= local8 self)

push, pprev

These just forward onto their only child (which will have an instruction that sets the accumulator, or the prev register in the case of pprev). push just pushes the accumulator value onto the stack. Since the abstract syntax tree doesn’t care about stack vs accumulator (it’s an implementation detail of the byte code, so to speak), we basically ignore it. We already took it into account when generating the instruction consumption tree.

bt, bnt

These are essentially ignored at this stage (they were taken into consideration in the control flow graph), and just forward on to their only child.

dup, jmp, link

These can also be ignored at this stage.


This indicates the end of a switch statement. These should have already been pruned (and their surrounding code should already be in the form of a switch stratement in the control flow graph), but there are cases where we have mid-identified degenerate switch statements. So if we encounter this, we generate a switch statement with a single (default) case.


The rest of the instructions involve load and store operations for global, local, temporary and parameter variables. So it is a matter of creating assignment operations (for the store opcodes) or values (for the load opcodes), and looking up the appropriate variable name.

	ldi 0 
	sat temp0 
	lst temp0 
	ldi 6 
	bnt code_0101 

	(= temp0 0)
	(while (< temp0 6)

Naming and symbol resolution

We’ve glossed over this so far, but coming up with the correct meaningful names for variables and tokens is important (not just for decompiling, but also disassembling).

There are a few different categories here:

  • names we can find out for certain (class names, instance names, property names)
  • names for which we have no information at all (local variable names)
  • values in the code that refer to objects, strings or selectors. All values are just 16-bit numbers, but some of them are pointers, and we need to try to replace them with the correct textual value.

Let’s go over each of them in more detail.

Known symbol lookups

The script resources themselves contain the names for classes and instances defined in that script – that’s pretty straightforward. We also need to reference superclasses though. They are generally referred to by their class number (just a 16-bit value).

SCI games have a class table resource that lists that basically maps a number to an index within a particular script resource. For instance, class #33 might be the 2nd class defined in script 988. For this reason, to build a mapping of class number to class name, we need to actually load all script resources in the game (or at least all those listed in the class table resource) and search for the class name. This table that we construct is actually fundamental not just for decompiling, but also compiling.

For property and method names, it is a little easier. Both properties and methods are identified by their selector number. SCI games have a selector table resource that is a direct mapping of selector number to selector names.

Heuristics for generating meaningful variable names

Unfortunately, there is no trace left of the original variable names in the compiled byte code. That means we don’t know the names for global variables, script variables, temporary function variables or parameters.

We do know which type of variable something is though, and we know its index. When the abstract syntax tree is generated during decompilation, automatic variable names are generated that simply combine the variable type and index: global25, or temp1, say.

We then perform a renaming pass that attempts to give more meaningful names. The following things happen:

  • We leverage an editable decompile.ini file which lists known parameter names for certain methods. For instance, it will name the first parameter to the commonly-overridden changeState method “newState”. Likewise, handleEvent’s first parameter is “pEvent”.
  • The first bunch of global variables tend to be the same across games, so we have a pre-defined list of what these should be named.
  • The first assignment to a variable in a function will attempt to generate a name based of what was assigned to it. For instance, if we see “(= temp0 x)“, we’ll rename temp0 to “theX“. It’s not perfect, but at least it helps give some indication as to what the variable might be used for.
  • When we assign to global variables, we store that information so that it may be re-used by subsequent scripts. For instance, if we encounter the code “(= global75  features)“, we’ll rename global75 to “gFeatures“. This will be picked up by further decompiles of scripts that reference global75.
  • The user can also guide the renaming of global variables and public procedures by giving them new names during the decompilation process.

Naming constants

Of course, it’s not only variables that need good names. We also want constants to be properly defined.

For instance, the Palette kernel call takes a subfunction as its first parameter. This is just a number, but there are eight different functions it might represent. sci.sh, the global header file, as these defined. Using the decompiler.ini file, we can indicate that the first parameter to Palette is one of these defines. That allows the decompiler to turn this:

    (Palette 1 97)

into this:

    (Palette palSET_FROM_RESOURCE 97)

We can also do this for variables of certain names. For instance, we can say the type property of a variable called pEvent should be one of the event type enumeration values defined in sci.sh. This lets us produce code like this, where it’s clear we’re handling mouse events:

	(method (handleEvent pEvent)
		(if (== (pEvent type?) evMOUSEBUTTON)
					(User controls?)
					(not script)
					(== (pEvent type?) evMOUSEBUTTON)
				(gEgo setMotion: theSMover (pEvent x?) (gEgo y?))
				(pEvent claimed: 1)
			(super handleEvent: pEvent)

Another scenario in which the decompiler.ini config file is useful is to identify parameters which might be selector literals. Some of the fundamental methods on the SCI object base class take selector literals as parameters (for example, the firstTrue method). From the decompiler’s standpoint, the value passed to this method is just a number. But we can tag it as being a selector so that we can generate more meaningful code at the call site. An example from Space Quest 1 VGA, where we know that the first value passed to the firstTrue method is a selector:

    (= temp0 (gCast firstTrue: #isKindOf Elevator))

This is assigning the first cast member that is a subclass of Elevator to the temp0 variable.

Defining these values/types for just a handful of common scenarios goes a long way to generating readable code right off the bat.

Another important scenario where we need to make some guesses is in the instance property lists. When an object instance is defined, you can override the default property values for its species. This property value is a 16-bit number as always – but it might be an offset into the script’s string table or said table. How can we know this? We can’t know for sure (we could get some false positives), but every property value is checked to see if its value matches one of those offsets. As a result, inventory items decompile correctly:

(instance Grenade of RInvItem
		view 564
		cursor 16
		signal $0002
		description "You have a small innocuous looking grenade."
		owner 58


Array bounds

As mentioned before, variables are referenced in byte code by their type and index. The notion of arrays doesn’t really exist. A function or a script just declares that it has, say, 10 variable slots. These could be 10 single variables, or perhaps 5 single variables and a 5 element array.

However, by examining how these variables are used we can get an idea of which parts of the variable block are explicitly referenced, and which parts are only referenced by index. As an example, in script 40 of Space Quest 1 VGA, we encounter this code:

		(holePoly points: @local1 size: 8)
		(shipPoly points: @local17 size: 8)

By examining this and other local variable usage, we come up with the following list of local variables, two of which we define as arrays (they appear to be lists of polygon coordinates).

	[local1 16] = [178 169 196 162 222 160 256 164 265 168 253 177 220 182 189 178]
	[local17 16] = [178 171 177 155 222 150 264 157 269 170 242 170 232 177 201 170]


Unlike temp, local and global variables, there is no explicit count of function parameters anywhere in the byte code. This makes sense, because SCI allows for a variable number of parameters for all functions. As a result, we need to scan the function for code that references parameters (like other variable types, they are referenced by index), and any usages of a rest instruction (which forwards unspecified parameters onto another function). From this information we can figure out the number of named parameters.

Function return values

In SCI, functions return values via the accumulator. The byte code offers no hint as to whether a function intentionally returns a value or not.

We make some attempt at guessing. If we encounter an opcode with no side effects (i.e. all it does is put something in the accumulator – no functions called or properties set) that is right before a ret instruction, then we’ll assume the function intentionally returns a value. This will affect how we generate the instruction consumption tree: ret instructions will consume the accumulator.

Our guess isn’t correct all of the time, but it ends up not really mattering from an accuracy point of view. The re-compiled code should still exhibit the same behavior (in terms of what’s “accidentally” left in the accumulator at function exit) as the original byte code.

Number formatting

Numeric literals in source code may be specified in decimal or hexadecimal (or binary, or by ASCII character). And they may be signed or unsigned.

In the AST, numeric literals are represented by a value node. The numeric value is always stored as an unsigned 16-bit value, but it can be tagged as being “negative”, or in “hex”. This doesn’t change the underlying value, it’s simply a clue as to how to present it when formatting it for output.

Of course, we usually have no explicit information in the byte code that helps us decide which way to output the number. As result, we need to apply some simple heuristics:

Any value that is a direct child of a bit-wise operation (whether it be a binary, unary or assignment operation) will be tagged as “hex”.

	(method (enable param1)
		(if param1
			(= state (| state $0001))
			(= state (& state $fffe))

Currently, any value that is larger than 32767 (the largest signed 16-bit value) will be tagged as negative. Obviously this isn’t always the right choice, but it tends to be.

	setMotion: MoveTo -108 224

Tracking script dependencies

Compiling an SCI script requires that any scripts than contain referenced classes or procedures from other scripts have those other scripts’ filenames listed in the use statements at the top of the script being compiled.

Thus, to generate a perfectly-compilable script, we need to scan all code and classes for references to public procedures and class names. Then we need to figure out the names of those scripts where they reside and add in the appropriate use statement in the AST.


The decompiler isn’t perfect, but typically it can decompile about 95 to 99 percent of a game into source code. Success is typically on a function-by-function basis. Luckily, if an error or unexpected condition occurs anywhere during the decompilation of a function, we can have the entire function fallback to assembly. This at least retains the ability to recompile code correctly, and also retains some symbol information. An example from Space Quest 1 VGA, Talker::startAudio:

	(method (startAudio param1 &tmp temp0)
			lap      param1
			sat      temp0
			pushi    2
			pushi    1
			callk    DoAudio,  4
			pToa     mouth
			bnt      code_0452
			pushi    #setCycle
			pushi    2
			class    40
			lst      temp0
			pToa     mouth
			send     8
			pushi    2
			pushi    2
			lst      temp0
			callk    DoAudio,  4
			aTop     ticks
			pToa     eyes
			bnt      code_046d
			pushi    #setCycle
			pushi    2
			class    RTRandCycle
			pTos     ticks
			pToa     eyes
			send     8


Note that I actually had to add an additional opcode that isn’t present in SCI. the lea opcode loads the address of a variable into the accumulator. It can also have a flag that indicates “use the previous value in the accumulator as an array index”. I could have changed symbol resolution for the operands to support referencing the accumulator, but the most straightforward choice was just to add an additional opcode called “leai“, which is handled specially during disassembly and compiling.

With a bunch more work, it should be possible to have the decompiler 100% effective (except for corrupted scripts, of course) – but I decided that the effort vs reward wasn’t worth it beyond this point, especially given the fallback to assembly. It’s good enough to be able to create a template game from and for people to easily write script patches or mods to existing games.

Code output

SCI Companion supports both the source code syntax of SCI Studio, and also a newer syntax that is much closer to that used by Sierra originally.

There are modules that output source code in either of these formats based on the given abstract syntax tree. However, there isn’t necessarily a one-to-one mapping of syntax nodes to source code. The abstract syntax tree code was mostly written when only the SCI Studio syntax existed. Some of the forms don’t map quite as nicely (or can be expressed more efficiently) in the Sierra syntax. Since the Sierra syntax is the preferred syntax, we’ll go through some of the additional transformations we do on the syntax tree as we’re formatting it as source code.

Do-loops don’t exist in the Sierra syntax, so they need to be converted into repeat statements that end with a breakif statement in place of the do-loop condition. An example:

			((= param1 (Event new: -32768)) localize:)
			(if (!= (= temp0 (self check: param1)) temp1)
				(HiliteControl self)
				(= temp1 temp0)
			(param1 dispose:)
			(breakif (not (localproc_0022)))

While-loops that are determined to be infinite are just converted to repeat statements.

Sierra syntax has a shorthand for nested if-then-else clauses: the LISP-like cond statement. When outputting an if-statement, if nested if-statements are detected, we use the cond syntax instead:

		((& (gEgo onControl:) ctlYELLOW) (Print {You can't do that from here.}))
		((& (gEgo onControl:) ctlFUCHSIA) (gEgo setScript: egoTouchesAcid))
		((== global166 1) (Print {You can't do that from here.}))

Sierra syntax supports n-ary operations for several operators, whereas the SCI Syntax only supports binary operations. If nested binary operations are found, we try to coalesce them into an n-ary operation (e.g. (+ a b c)).

The if-then-break and if-then-continue forms are turned into the Sierra-specific breakif and contif statements.

Another thing to note is that there are some forms the decompiler will never generate:

  • No for-loops are ever generated, as they are simply while loops with some initialization code prior to the loop start. With some extra effort I could have tried to guess what code should be put into a for-loop‘s initialization and afterthought parts, but I did not deem the value worth the effort.
  • Operator assignments like += or -= will never be generated (they will just retain the regular form (= a (+ a 1))). Another “nice to have” but not essential feature.
  • The Sierra syntax supports a switchto statement with implied case values (starting from 0). The decompiler will always just output switch statements, however (which have explicit case values).
  • The Sierra syntax supports (rarely-used) multilevel break and continue statements, but these will never be output. In fact, the control flow analysis does not handle these properly, and so decompilation will likely fail if this pattern is encountered. This will cause us to fall back to assembly.


Hopefully this has been an educational walk-through of the details involved in going from byte code to source code.

There are of course more subtleties and complexities that I have glossed over in these blog posts, but the SCI Companion source code is available for perusal.


Decompiling SCI – part 3 – instruction consumption

Here’s a link to part 1 of this series.

Another fundamental concept we need to introduce is instruction consumption.

The basics

Each SCI instruction (opcode + operands) “consumes” a certain number of values from the stack, or the value of the accumulator or prev registers. Likewise, it may “generate” a result that gets pushed onto the stack, or placed in the accumulator or prev register.

Let’s look at a simple example. Consider the following code:

(= localVar (+ param1 3))

and its corresponding assembly instructions:

lsp param1 
ldi 3 
sal localVar 


How do we go about actually constructing the former from that latter?

We can start from the last instruction (sal localVar), which means “store the value of the accumulator in this local variable”. From this, we know we we’ll have an assignment operation, and the value that is being assigned will come from the value in the accumulator.

So going backwards, we see the previous instruction is add. This satisfies our need for an accumulator value, since add places its result in the accumulator. So the result of the add is what will end up being assigned to the local variable above.

Of course, add consumes an accumulator value itself, in addition to popping a value from the stack. So we work backwards again trying to find an instruction that pushes a value onto the stack, and the next instruction that places a value into the accumulator. Luckily, in this case, these are immediately satisfied. ldi places a value in the accumulator (3), and lsp pushes a value onto the stack (the value of param1).

Essentially, we’re building a tree of instructions, where a node represents an instruction and a node’s children represent instructions that generate the data needed for the node’s “consumption”. So in the above example, we’d have:

  • sal local0
    • add
      • ldi 3
      • lsp param1


In practice of course, these trees become quite large and nested quite deeply. SCI has some fairly complex instructions that can consume arbitrary amounts of stack values.

The problems

Things aren’t always so clean as in the previous example.

For instance, it is not uncommon for a value in the accumulator to be “consumed” by multiple instructions.

Consider the following assembly from the spotEgo method in script 80 of King’s Quest 6:

	pToa spotEgoScr 
	bnt code_01f6 // Consumes the accumulator, which is spotEgoScr.
	pushi 92 // $92 setScript
	pushi 3
	push // Consumes the accumulator, which is spotEgoScr.
	lsp param1 
	lag global2 
	send a 

The value in the accumulator is used twice. This decompiles into the following code, which is a pretty common pattern (branch on something, then use the value that was branched on):

		(if spotEgoScr
			(global2 setScript: spotEgoScr 0 param1)

Speaking of branching, what happens if we encounter a branch or jump instruction while backtracking? Suddenly, we can’t form a good idea of what constitutes the statement we’re trying to build, since the shape of our instruction consumption tree would depend on which branch was taken.

Tying it together with the control flow graph.

Both the control flow graph and the instruction consumption logic work together in determining the final decompiled source code.

The control flow analysis should have removed any stray branch instructions (jmp, bt or bnt) in the sense that they would have turned into semantic control flow graph nodes (if statements, loops, etc…), leaving just non-branching sequences of instructions. So our instruction consumption code doesn’t really need to deal with them anymore.

However, it does need to deal with the problem of not being able to satisfy instruction consumption in the current sequence of instructions. So let’s see how that might work.

Let’s revisit what we have in our control flow graph. Yes, we have all those semantic nodes: if, loop, switch and so on. But we also have “raw code” nodes in the leaves of the graph. That is, the condition node in a loop will contain the raw set of instructions that comprise that condition.

So if we take our example from the previous section, after doing our first pass of instruction consumption, we’ll end up with something like this:

      bnt  [01e5]
        pToa  [01e3]
      send  [01f2]
        pushi  [01e7]
        pushi  [01ea]
        push  [01ec]
        push0  [01ed]
        lsp  [01ee]
        lag  [01f0]

You’ll see that we were not able to find an accumulator value to satisfy the push instruction. So we tagged it as “needs accumulator”.

On a second pass, we’ll try to work backwards to find the appropriate value. Below, you’ll see that we “cloned” the pToa value from above:

      bnt  [01e5]
        pToa  [01e3]
      send  [01f2]
        pushi  [01e7]
        pushi  [01ea]
        push  [01ec]
          pToa  [01e3]
        push0  [01ed]
        lsp  [01ee]
        lag  [01f0]


Working backwards doesn’t just mean returning to the original set of raw instructions and scanning backwards, of course. Then we run into the problem again of branching interfering with a static known path to our current instruction.

Instead, we need to follow the control flow graph hierarchy “up and backwards”. And the way we do that ends up being fairly complex, and changes depending on the type of the node in the control flow graph.

Another point that is important to bring up: Some of the control flow graph nodes themselves need to be treated as though they generate a value for the accumulator. For instance, if-statements, switch-statements and isolated compound conditions are all treated as such. That is, if we can’t find an accumulator-value-producing instruction to satisfy our instruction consumption, and we encounter an if node while navigating “up and backwards”, then we’ll use that if node as an accumulator-value-producer. This is a pattern we see often in source code like this (this would be the equivalent of the ternary operator in most languages):


(= someVar
    (if blahblah 5 else 2)


Of course, then we need to make a call as to whether we can remove the if node from its previous spot in the instruction consumption tree, or we have to leave it in and clone a new one (resulting in possibly incorrect code since we’ll evaluate the if-statement twice). These subtleties and complexities help to illustrate some of the difficulties in implementing an accurate decompiler.

During this phase we also do some analysis to classify loops: are they while-loops, do-loops or infinite loops? We can analyze the structure of the loop to figure this out. For instance, if the latch node has two successors, and the loop head node has only one, we know it’s a do-loop (the loop condition comes at the end).


At the end of the instruction consumption phase, we have now generated a “consumption node” tree that incorporates both information from the control flow graph, but also more detailed information on how individual code statements are constructed: flat sequences of instructions have been re-organized into hierarchical forms. We’re now ready for the next phase, which involves constructing the abstract syntax tree for the source code.

Below is an example of what the instruction consumption tree might look like. First, the decompiled method:

	(method (constantRocks &tmp temp0)
		(rCliffs cheatCount: 0)
		(= temp0 0)
		(while (< temp0 7)
			((= [newRockStep temp0] (RockStep new:))
				x: (if argc (- 320 [local246 temp0]) else [local246 temp0])
				y: [local262 temp0]
				cel: 3
				rockPointer: temp0
				corner: (if (== temp0 6) 1 else 0)
			(if (< temp0 6) ([newRockStep temp0] addToPic:))
			(++ temp0)


And then, the instruction consumption tree that was used to generate this:

  link  [0350]
  send  [0359]
    pushi  [0352]
    push1  [0355]
    push0  [0356]
    class  [0357]
  sat  [035d]
    ldi  [035b]
      send  [03b0]
        push1  [0366]
        push1  [0367]
        push  [037a]
              bnt  [036a]
                lap  [0368]
              lali  [0378]
                lat  [0376]
              sub  [0373]
                pushi  [036c]
                lali  [0371]
                  lat  [036f]
              jmp  [0374]
        push0  [037b]
        push1  [037c]
        lsli  [037f]
          lat  [037d]
        pushi  [0382]
        push1  [0384]
        pushi  [0385]
        pushi  [0387]
        push1  [038a]
        push  [038b]
          lat  [037d]
        pushi  [038c]
        push1  [038f]
        push  [039c]
              bnt  [0394]
                eq?  [0393]
                  push  [0390]
                    lat  [037d]
                  ldi  [0391]
              ldi  [039a]
              ldi  [0396]
              jmp  [0398]
        pushi  [039d]
        push0  [039f]
        pushi  [03a0]
        push0  [03a3]
        sali  [03ae]
          push  [03ab]
            send  [03a9]
              pushi  [03a4]
              push0  [03a6]
              class  [03a7]
          lat  [03ac]
          bnt  [03b7]
            lt?  [03b6]
              lst  [03b2]
              ldi  [03b4]
          send  [03c1]
            pushi  [03b9]
            push0  [03bc]
            lali  [03bf]
              lat  [03bd]
      +at  [03c3]
      jmp  [03c5]
      bnt  [0364]
        lt?  [0363]
          lst  [035f]
          ldi  [0361]
  ret  [03c7]


The next post ties everything together and summarizes the final steps.

Cascadia Quest blog

Development blog for Cascadia Quest

The Space Quest Historian

Hi, I’m the Space Quest Historian.

Harebrained Schemes

Developer's blog for IceFall Games

kosmonaut's blog

3d GFX and more


Turn up the rez!

bitsquid: development blog

Developer's blog for IceFall Games

Game Development by Sean

Developer's blog for IceFall Games

Lost Garden

Developer's blog for IceFall Games


Developer's blog for IceFall Games

Casey Muratori's Blog

Developer's blog for IceFall Games

Blog – Coherent Labs

Developer's blog for IceFall Games

Rendering Evolution

Developer's blog for IceFall Games

Simon schreibt.

Developer's blog for IceFall Games

- Woolfe -

Developer's blog for IceFall Games

Fabio Ferrara

Game Developer

Clone of Duty: Stonehenge

First Person Shooter coming soon to the XBOX 360

Low Tide Productions

Games and other artsy stuff...


Just another WordPress.com site

Sipty's Writing

Take a look inside the mind of a game developer.

Jonas Kyratzes

Writer & Game Designer