The most difficult engineering challenge in Fireflies was dealing with tombstoning. For those unfamiliar, tombstoning is Microsoft’s term for what happens when your app is interrupted. An interruption might be, for example, the user receiving a call, locking the screen, or hitting the home button. As of the game’s publication, the phone did not have multitasking support. Therefore, during an interruption, the app gets a notification that it’s being tombstoned, then its process is terminated. This means that every well-behaved app needs to expect these interruptions and be prepared to save its state so it can resume the new process were the old left off.
To accomplish this, the game needs to be completely serializable no matter which state it’s in. This turns out to be quite a daunting task to do correctly. Many games in the Marketplace just punt entirely and only remember basic things like your current level. Receive a phone call at the end of the boss fight? I guess you get to start over! Just beat your old high score and accidentally bumped the ad? Sucks for you!
This is, of course, unacceptable behavior. We were pedantic about making sure the game can handle any interruption at any time, and the exact game state will be saved, down to the positions of the little fireflies in the jar. As a first step, we need to decide how to serialize the game state.
Some people roll their own serialization, typically with a custom interface,
perhaps something like IBinarySerializable. When performance is an issue,
this might be the necessary option, but it comes with several drawbacks.
Mainly, you spending time trying to debug why your objects are full of garbage
since your forgot to read in an int somewhere and screwed up the stream. If I
wanted to deal with that kind of crap I’d be writing in C. Thus, we chose to
avoid this on the grounds that I’d rather be making a game than figuring out
the best way to serialize reference cycles in my object graph. The good people
on the .NET team figured out all this hard stuff already.
For a small, simple game, the built-in methods are perfectly fine. The two
main options are XmlSerializer and DataContractSerializer. The differences
didn’t really matter for our simple case, but we went with
DataContractSerializer, since which members are serialized are opt-in rather
than opt-out. We didn’t want to accidentally serialize a RenderTarget2D or
other ephemeral resource.
Not that the built-in serializer doesn’t have its own drawbacks. In order to serialize private and read-only members, the serializer must use unsafe code. Only you can’t use unsafe code on the phone. So no private or read-only members, I guess. Well, good thing we already wrote the game code. At least I won’t have to cringe looking at it.

Of course it’s not enough to just write your entire program state to disk. An important part in making serialization work smoothly is keeping the persistent data (stuff you need to serialize) separate from the ephemeral data (stuff you can re-create next time). For example, all of our assets such as textures are loaded into one object, and no game state objects hold onto any references to any assets. The asset-holding object is passed to every update or render function that needs them. Now we don’t need to worry about fixing up game state objects after deserializing them, since they don’t have any references to ephemeral resources. This kind of separation is a good idea anyway, but it’s absolutely crucial if you want to be able to quickly and easily save the persistent data.
There’s also many special situations to consider. What happens if the user is entering their name for a highscore in XNA’s built-in keyboard input control when they hit the home button? Turns out the control returns the empty string before the process exits, which left a blank name in the highscore list. Therefore, the game has to check on startup if the name field for the most recent score is empty and, if so, bring up the dialog again. What happens if the game is tombstoned during first initialization? The game saves out an uninitialized game state, then happily loads in said state next time and crashes. So the game has to be careful to only save after initialization is complete.
So, even with the built-in serialization, it still took over a week to get saving and loading fully working. Solving corner cases took a lot of time, but I’m really proud that our game handles them. Even when multitasking support arrives, it’s still nice for the user to be able to back out of your app and return later to find the app exactly as it was. So make sure to take care of your users. They’ll be much happier for it.