If you’ve read any of my previous posts, you know I’ve been developing games for the Windows Phone platform for the past 3+ years. A few months ago I decided to set phone development aside and tackle the relatively new Windows 8 Store beast. Because of the timing, I figured a port of my North Pole Invasion game would be perfect for a December release. Since XNA is no longer available, I would be using MonoGame for the port. As it turned out, moving to MonoGame was fairly straightforward, with only a small stumble encountered. On the other hand, it was an unexpected speed bump in certification, not MonoGame, that caused me to reach that self-imposed deadline by the skin of my teeth.
Porting the game from the phone went smooth, in part because I had already ported my game engine framework to work with MonoGame on Windows 8 earlier this year. I let the ported framework sit for a few months as I returned to my bread and butter – Windows Phone game development. It wasn’t until after releasing my hit Halloween game in October, Pumpkin Smash 3, that I decided to get down to brass tacks and start on a Windows 8 Store game.
When porting my framework, all the parts I thought would cause trouble actually caused no trouble at all – my sprite classes, the 2D cel animation engine, and the 3D model classes just worked perfectly with no tweaking. Surprisingly, it was the audio stuff that caused minor issues.
First was the way I was handling music playback. On the phone, I use Song.FromUri() to initialize a Song object and play back music. I couldn’t get this to work in MonoGame. The solution was simple: load a Song object through the Content Manager, then play it. Done.
I had a very similar problem with looping sound effects. On the phone, I use TitleContainer.OpenStream() to load in a SoundEffectInstance. Doing this with MonoGame caused a consistent crash. Again, I resorted to loading the sound through the Content Manager first, then calling CreateInstance() on it to initialize my SoundEffectInstance object, which is required for looping sounds. Problem solved.
Now let’s fast forward to certification, because that is where things really started breaking down. My first attempt failed within a few hours of submitting it. The certification team sent along the error report with screen shot of where the game crashed, but no crash dump. Flying blind, I made some knee jerk code changes and re-submitted.
A few hours later it failed again. This time I sat back and really started thinking about what could be going on. The game had tested flawlessly on a 64bit Windows 8.1 Pro PC, a 64bit 8.1 touch screen notebook, and a Dell Venue 8 Pro tablet running 8.1. I reached out to my local Microsoft contact with the limited information I had, and he elevated my problem to see if we could get a crash dump.
I decided to submit another build, and this time I specifically requested a crash dump during the submission process in the “Tester Notes” section of the submission page. Luckily, I did receive a crash dump on that failure. The dump revealed…almost nothing of note, other than a reference to crashing in combase.dll, a Windows library. Using this new, limited bit of information, I reached out to my friends to see what they could make of it.
As a last resort, I emailed a higher-up over at Microsoft in Seattle, whom I was fortunate to meet during my trip there earlier this year. He forwarded my issue to someone on the actual Windows team, and he wrote back with some enlightening information. In a nutshell, the crash in combase.dll might be attributed to doing “too much work“. He recommended “staggering” the loading of the level. In my case, it meant staggering both the loading of graphics assets and the initialization of all the physics bodies used in the level.
I accomplished this by turning my initialization method into an asynchronous routine. Then, between bouts of “heavy work” (content loading and physics initialization) I inserted very short (less than half a second) async Await() delays. I was not fond of this solution, but it was the only thing I could come up with. I reached out to some other game developer friends, and they all agreed my solution is the one they would take, as well. Crossing my fingers, I submitted to certification one more time, and it passed.
I should note that this same game on the phone does not require these delays while loading the level. I initialize the exact same physics bodies and similar graphics assets (higher resolution on Windows 8), and it doesn’t have problems. Also, it’s only the physics levels in the game that required this delayed loading technique. The snowball tossing part of the game, which does not use Farseer physics, did not have problems crashing, so I was able to leave that part alone.
So what did I learn from this? I learned that MonoGame is awesome sauce, and it makes porting from Windows Phone XNA over to the Windows 8 Store very easy to do. The audio issues I had with MonoGame were very minor, and were solved in minutes. I also learned that the Windows 8 core library known as combase.dll will barf when too much work is requested at once or consecutively. Solution? Load small, common bits and pieces of the level up front and keep them in memory, or stagger the loading of the game with delays.Tweet