When making a cross platform game, XNA is generally not a good choice because it depends heavily on the Windows-only .NET framework and DirectX. In my case, the Mac OS X port came as an afterthought. After creating the game Seven Dimensions for the 7 day FPS challenge, some people requested a Mac version. I thought it was impossible to recompile an XNA game for Mac OS X, but a friend of mine said it could be done! I decided to go for it. If it worked, it would make XNA a lot more versatile.
Step one: Get a Mac
At first I tried to use Mac OS X in VMware. Running Mac OS X was surprisingly easy, thanks to a pre-made solution found on the internets. But I didn’t succeed in running any type of 3D game at all. I guess the VMware graphics driver can’t handle slightly more complicated graphics. On top of that, Xcode seemed to be impossible to install. Fortunately, I could borrow a Mac from a friend.
Step two: Setting things up
There’s an excellent guide here (part 2 here) which describes everything you need to download and install. However, that guide is aimed at 2D games (using SpriteBatch only). There are some small differences if you want to use 3D graphics with custom shaders. Most importantly, you need to use the develop3d branch of MonoGame (at the time of writing).
Any shaders you want to use have to be compiled into an intermediate MonoGame format. To compile the shaders, you need a Windows computer. Open the 2MGFX solution found in the develop3d branch under Tools. This solution depends on additional dependencies which you have to download separately. Go to the develop3d branch of the github repository and go to the ThirdParty folder. Click on the green “Libs” folder, download that as a zip file and place it in your local ThirdParty/Libs folder. Now you should be able to compile the 2MGFX solution. The compiled program is the command-line tool you have to use to convert your .fx shaders to .fxg shaders. Make sure to open the .fxg shader in a text-editor to see if there is shader-like code in there.
You should test your setup using the CartBlanche sample Particle3DSample. If it compiles and runs without crashing immediately, you’re ready to port your game.
Step three: Porting your game
Prepare your project as described in part two of the guide mentioned above. Your code should compile almost directly. But unfortunately, you will encounter problems when running your game. The problems are very project-specific. These are the problems that popped up in my project:
- The Game class was destroyed instantly causing an exception that the Game class was used while it was disposed. It turns out that Mono handles the “using (game = new Game())” syntax in program.cs differently. Simply rewrite this code to avoid the “using” syntax.
- EffectParameters were not found. This can be caused by two things. First of all, if a parameter is not used in the effect, you can’t set it. Secondly, texture effect parameters cannot be found. The texture should be set using the texture sampler EffectParameter instead.
- The sampler settings defined in the shader were lost. You should set these settings from c# using the GraphicsDevice.SamplerStates collection.
- The Mouse.SetPosition function does not work. I worked around it, maybe it’s fixed in a later version of MonoGame.
- The viewport position offset was mirrored vertically. This is easily fixed by correcting the offset of the viewport you create.
Step four: Hope for the best
MonoGame uses OpenGL instead of DirectX, which can cause obscure problems. Your game might behave strangely on some hardware for no clear reason, especially if you use uncommon graphics features. Seven Dimensions uses line-drawing in combination with depth testing, which is very uncommon. The depth testing didn’t work for the line drawing, so I had to rewrite the game to use triangles instead. There are still other problems on older hardware which I haven’t been able to solve yet.
In total, I spent one day (8 hours) on the port. That’s very little considering that most time was spent on figuring out how to use MonoGame for 3D. The resulting port is not perfect, but MonoGame is still in active development so it will only get better!