Porting ARMED! To OUYA
This is a "live blog" of my port of ARMED! to the OUYA console using MonoGame. The goal today is to get it running well enough to load gameplay and maybe be able to play a little.
The port is now complete... read further to see the details and feel free to ask questions below!
Starting - 3:04 pm
Started a bit late today, but I feel good about getting it working quickly. The first step i'm going to take is creating a dummy project using the MonoGame Android template. This will show me what files I need to get ARMED to start under Android. I just copied the template out of my clone of the MonoGame repo into the VS2012 templates folder in My Documents.
James is here too, he is getting Xbox Gamepad support into the Windows 8 Store version of ARMED!. Our plan is that as he is getting that done I should have the game running on the OUYA and we can go thru the UIs and maybe play using the gamepad.
Got the dummy Android project created. Going to first build and deploy that and verify it works. Then i'm going to move the Android specific files into an Android subfolder.. this is ideally how we want it in the main ARMED! project (we support 5 other platforms already) and this lets me test if I can make the changes without breaking anything.
Trying to blog and port all at once is hard... but I think its worth it. Dummy project runs on the OUYA now:
It is looking hard to put the 'Resources' or 'Assets' in a subfolder. Going to revisit this later. Moving forward to merging the dummy project with the ARMED! codebase itself.
Merging the dummy project... had to add a OUYA constant to #if some things around. In this process a diff tool like BeyondCompare is your friend. Don't forget to check the AssemblyInfo.cs for differences too... had to #if OUYA a few lines there. Noticing a few other libraries we depend on that I need to port like ServiceStack.Text ... i'll hack that out for now and look at it later.
We have 4 projects to port... it took a little while doing merges. Content project now builds OUYA ready content. Now to build a new OUYA solution for ARMED! and add the projects in one at a time making sure they build. I figure this is gonna be the messy part as I disable stuff that isn't critical to getting something to render.
I'm a big dummy... totally forgot about the OUYA template in MonoGame. Had to merge in the few differences and reference the Ouya.Console.Api assembly for OUYA specific APIs. Got a solution for the ARMED! OUYA build and all the projects added. Got some build errors from incorrectly included files to clean up.
Bah... got everything building except some of these mystery errors. It cannot find certain namespaces of things that clearly exist. I suspect the build is overwriting intermediate files somewhere and causing this oddity. Investigating.
So worked around the mystery errors... right clicked and built the offending projects on their own then unloaded the project from the IDE. This trick made those errors go away... which means it truly is something in the build overwriting intermediate build data.
Now back to stubbing out network stuff that doesn't need to work just yet.
Ugh.... AndroidGameWindow is an ugly. It is returned instead of GameWindow on Android/OUYA. This causes pain to the users porting projects like ours where we assume Game.Window is a GameWindow object. Going to #if OUYA my way around it, but look for a pull request from me soon fixing this mess.
Just have a couple more errors to fix before I can attempt to run things on the OUYA.
Deploying to OUYA... crossing fingers.
I figured it wouldn't work on the first try. Looks like some simple errors based on file system stuff. Fixing now....
Easy fix. The code was trying to use regular old System.IO calls for working with directories and files. Well Mono for Android supports IsolatedStorage. Just had to fix up our #ifs to use the same code for OUYA as we do on Windows Phone.
Now it is totally running!
Not much to look at yet... it is flickering black and blue with just a bit of a garbled FPS counter. I suspect this is bad content... in particular textures. Investigating!
It took 4 hours in between me discussing various UI GamePad navigation designs, blogging here, and making dumb mistakes... but ARMED! is running on OUYA!
The previous issue wasn't bad textures... it was a dumb #if which kept the splash screen from loading. The UI is basically working now... James is checking in code now to let us press buttons and get a level loading. In theory... the hard part is over!
Took a little "victory break" and i'm back at it. James abandoned me so i'm off to finish off the gamepad input that he started.
Got real basic gamepad navigation of the menus working... now i'm loading a level.
It is taking over 5 minutes to load a level... I know we have a lot of content and I am running in the debugger, but that is way way too slow. I suspect maybe the Android code is doing something dumb still and is decompressing the DXT textures... which it doesn't have to do on OUYA which uses a Tegra chip. Investigating.
Well part of the slow loading was textures. By default in MonoGame for Android DXT formats were decompressed... which is total madness, but legacy left over from before we starting working on content processing. Mono for Android seems to be missing the correct PixelInternalFormat enum values... so I hacked it by casting the correct hex code which luckily worked. This really isn't the "right way" to do this... I should be using the GL extensions info to detect if DXT is supported on the hardware.... so another thing I will need to fix in the coming week.
Still the loading is slow... I suspect the threaded loading code isn't working as expected. Going to disable it and debug further.
So it was our threaded loading code... no clue why. We had a flag to disable it and now at least loading progresses to the end, but it crashes after that. I have to say my experience so far debugging in Mono for Android has been bad. If I sit too long at a breakpoint the debugger detaches from the OUYA. This seems to be an known bug, but I've not found the fix. Let me know if anyone reading knows the solution to it.
James has returned and he has the gameplay camera controls working... so off to debug the crash after loading so I can test it.
Finally after struggling with a bunch of Android-isms I got ARMED! gameplay working on the OUYA with camera controls:
The crash during loading was Android trying to be "helpful". Since loading was taking so long I figured it would be best to skip the threaded loading to speed up iteration. Well Android will terminate your app if it stops for too long in the main UI thread... like what would happen in loading. You would think... hey this is a debug build... it should let the code be as slow as it wants, but these are the same people that decided to use JAVA for an OS. /RANTOFF
Summary - 10:05 pm
So i'm calling it a night. My goals were pretty much met and as I expected it was a rather easy to port ARMED! to OUYA. Most of my difficulty came from my inexperience with Android and Mono for Android and outright dumb mistakes on my part.
I will spend some time this week doing some cleanup and fixes and try to get a preview build of ARMED! into the OUYA store in the next week or two.