Bringing Your Games to Android

Published March 10, 2010
Advertisement
Bringing Your Games to Android

How to port native code C/C++ games to Android
What API's native code games can use

You don't have to use native code if you don't want. Android uses the Dalvik VM for Java, and it's fast enough for most games.

Native code is a good choice is you need best speed, and/or your game is already written in C++.

The Android Native Development kit enhanced the Android SDK. On Monday they released R3, which is based on a more recent GCC toolchain, supports OpenGL ES 2.0, and Android 1.5 and higher. It works on Windows, Mac, and Linux.

It's based on the GNU toolchain, so you need to install the Cygwin package if you plan to use it on Windows.

1. Convert the game to a shared library.
2. Port to the NDK API's (OpenGL ES, etc)
3. Compile the game using the NDK
4. Write a small Java application that calls the shared library.
5. Package all art assets into the game's APK
6. Profit

What are the difficulty of these steps?

Build system - easy
Game engine - easy
portable libraries - easy
art assets - easy
platform API calls - medium
control system - hard

The control system will be the most alien, moving to a touchscreen and accelerometer.

Your game will be an APK file, which is a ZIPfile containing a classes.dex, which is your Dalvik VM code. C code will be compiled into SO (shared object) files.

The Android platform is based around the Dalvik VM. In order to show up in the marketplace or launcher, Android wants Dalvik APK files

Some API's are only available in the Dalvik VM, most significantly sound.

Must be in Java -

An activity - Marketplace, Launcher, Application lifecycle (i.e. main)
A GLSurfaceView - screen real-estate and input events
A GLSurfaceView.Renderer - EGL context creation, resizing, rendering loop
A wrapper class for the game's shared library, loading the shared library and using JNI to call the shared library.

JNI is the Java native interface, which is a standard way for Java to call C/C++ API's. It allows the Dalvik VM to call native code. Overhead is about 500 instructions per call. There's extra overhead talking to big chunks of memory by using "direct buffers" to move data blocks back and forth.

Converting a game to a shared library. Provide JNI entry points for calling native game code for start, stop, key event, motion event, surface created or changed, or step.

Available native API's include libc (malloc, fopen, etc), libm (cos, sin), libz (zip), liblog (Android specific logging, as an alternative to printf), openGL ES 1.x and 2.0. And more libraries are coming.

C/C++ apps can link to their own static libs.

What's missing? C++ exceptions, RTTI, and STL (although there are some third-party STL's that work), hardware floating-point, Audio API's (but you can call back to Java), and Debugging symbols (although there's logging).

Native code can access resources in the APK file. Store your data file in the res/raw directory. A hack is to give it the .mp3 extension so the compressor won't compress the data and you can access it directly.

Their big test-bed was a port of Quake. It consists of 200 lines of Java code. About 2500 lines of new C++ code had to happen, mostly to get old OpenGL to work in a system that didn't have the deprecated calls. One problem is that glQuake assumed the driver could manage an unlimited number of textures, so they had to implement a texture cache to map files on the SD card into the application address space. Using a simple LRU scheme, they kept the "good" textures close by.

Another problem for Quake is that their game data is too large to store in the APK, so they ended up putting the data on a web server, using http to download the data to an SD Card. Remember to check the data's integrity, as it'll be available to any SD Card reader.


Q&A

Q: Can I use a different compiler toolchain to, for example, enable hardware floating point.
A: Don't. It might work, but you'll likely lose forward compatibility.

Q: Can I use the private API's, like the native audio API's?
A: Don't. The private API's aren't set in stone.

Q: What happens if Android is ported to non-ARM architecture?
A: We'll cross that bridge when we come to it. Most likely we'll allow multiple shared native libraries bundled in, and we'll load the correct one at runtime.

Q: How can I get more RAM for my game?
A: The Android heap is 16-24 MB. Your best bet is to mmap a file on the SD Card as and access it for assets.

Q: Is the Android memory-protected?
A: Yes. Messing with memory only hurts your own app's address space.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement