CLM logo Development Blog by CLM

Portable audio with FMOD

I definitely need to start following gamedev news more closely — just a moment after we integrated openal-soft for Android version of our framework, Firelight Technologies has made FMOD Studio free for indie devs*! What does this mean for us? FMOD is used in thousands of commercial titles (and that should prove it’s quality), provides great documentation and has a very clean and simple portable API.

Our audio subsystem is using simple handle manager to provide multiple backends (OpenAL, XAudio2) so integration of FMOD should be pretty simple, right? It took me just about 3h to have it up and running at the same functional level as other backends, at least on Windows. With iOS build we faced very strange problems, it looks like the provided libraries contain duplicated object files and that caused duplicate symbols at the linking stage. To confirm this:

$ lipo libfmod_iphoneos.a -thin armv7 -output libfmod_iphoneos_armv7.a
$ ar -t libfmod_iphoneos_armv7.a | sort | uniq -d
fmod_optimised_routines_noopt-ACB1F04BF6036DC3.o

After manual fix of the libraries I was able to complete the build. I hope that this will be fixed in the next FMOD Studio release, till then we need to use ‘fixed’ library.

* indie in this case means game budget under $100k.

How we organize our projects

Today I want to share a little bit information about how our projects are organized from the technical side. As a foreword I should mention that 99% of our code is written in C/C++ and we’re using Objective-C only for communication with iOS.

One of our fundamental concepts is that we should share the most of the code between our projects instead of copying it. That’s the reason why we have a separate Framework project. Every one of our games or prototypes is using this Framework and during the development we’re trying to expand it with additional features. Currently it’s responsible for game states, memory, resources (Textures, sounds and audio streams), GUI, input, social features (leader boards, achievements) and simple data storage. When we think that some part of game code is reusable, we try to make it a part of the Framework.

Framework is also working as a layer between operating system and the game code, so there is almost no platform specific code in games. Currently we’re supporting iOS (iPhone, iPod Touch, iPad), OS X and Windows. System specific part of the Framework have API in C and this simplifies making it cross-platform.

Compilation of our Game for iOS looks like that:
1) compile Framework to framework.a
2) compile External Libraries to libraries.a
3) compile Game to game.a
4) copy .a files to Xcode project template that implements API, build and link it together

Xcode project may be customized by additional scripts to change project name, version, etc.

We store our projects in Git repositories. Whole building process is automated and we’re using Jenkins for continuous integration. We’re able to download latest builds from it with AdHoc distribution which is pretty great.

I think that this process works well for us and we’re going to expand it further in the future.

As a final note I just want to mention that our Framework is called Wombat ;)

Notes on using NSURLRequest

There are a few cases where NSURLRequest becomes handy. For example, we are using it to resolve redirects for URLs and decide where should we open the resolved URL (ie. inside App, Safari, AppStore). It’s possible to make a subdomain like http://review-game.yourdomain.com which redirects users to the AppStore. In my opinion this is a good separation between action and custom URLs — in case that Apple changes anything in review URLs, we can just change URL redirection on server and it works without the App update.

Review URL is a tricky example, because there is a direct link to the App review form for iPhone/iPod, but for iPad there is no such thing and we need to redirect user to App page. We solved it with a simple PHP script:

<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$iPad = strstr($userAgent, "iPad") ? true : false;
$iPodURL = "http://custom-link-for-ipod.com";
$iPadURL = "http://custom-link-for-ipad.com";
$URL = $iPad ? $iPadURL : $iPodURL;

header("Location: $URL");
exit;
?>

There is only one catch — there is no device information included in default NSURLRequest user agent! Default user agent is AppName/Version CFNetwork/485.13.9 Darwin/10.7.0 (versions may vary).

Fortunately it’s very simple to change it, but instead of NSURLRequest we need to use NSMutableURLRequest. Then it’s possible to change userAgent:

NSString* userAgent = @"My custom user agent";
[request setValue:userAgent forHTTPHeaderField:@"User-Agent"];

We decided to include App name, version and device information and that’s currently enough.

Debugging iOS HTTP connections with Fiddler

Recently we were experimenting with NSURLConnection and for some reason it was not working as intended. URL received in connectionDidFinishLoading was different than the one from redirects done on our server and verified in the browser. We double checked the implementation and decided to take a look under the hood and see how the connection is actually performed.

There is a great tool for Windows called Fiddler2, HTTP debugging proxy. With a very small amount of configuration it’s possible to see all HTTP requests done from the device.

In the Fiddler just check “Allow remote computers to connect” in “Tools” -> “Fiddler Options” -> “Connections”. On the device edit connection configuration and set IP address of the PC with Fiddler as the proxy address and 8888 as the proxy port (can be changed in Fiddler configuration). It’s as simple as that!

And what about our problem? We forgot about caching! After changing cachePolicy of NSURLRequest everything works perfectly.

It might be a little strange that iOS developers write about Windows tool, but we are using multiple platforms in our daily work. And if you’re looking for a cross-platform alternative there is one called Charles but it’s not indie friendly (paid, I mean).