|
Features

Mobilecore: A Cross-Platform Framework For ARM-Based Mobile Games
Mobilecore
on Pocket PC
As
your game will be derived from the Core
class, a Pocket PC version will only require a Pocket PC specific
version of the Core
class, with the same interface as the Symbian version. Luckily,
this is not a problem.
The
biggest "problem" on the Pocket PC is the fact that, just
as under Win32, we start out in C. A WinMain
function is the entry point of the application. The WinMain
will create a window for the application, prepare the device for
full-screen graphics output, instantiate and initialize the Core
object, and start the event loop and Tick()
mechanism.
About
this full-screen graphics output: On the Pocket PC this is usually
handled by the GX library, which is provided by Microsoft. There
are some good alternatives, but I'll stick to GX for the moment.
The
problem with GX is that it does not get rid of the title bar of
the application: There's an area at the top of the screen that does
not respond to stylus presses and where the clock sometimes flickers
through. Getting rid of the title bar is quite a task. It tends
to return whenever the system updates it, which is often: Alarms,
the battery icon, and a few other things all re-display the taskbar.
Therefore, quite a bit of effort is put into making sure the thing
stays away.
Another
problem with GX is that it offers the choice between direct or buffered
access to the device frame buffer. As some devices have rotated
frame buffers, doing a direct blit is not going to do the job. To
make things worse, some iPaqs (the 3800 series) perform terribly
unless you write directly to a hard-coded frame buffer address.
If you want to know all the specifics, check out the Core
implementation for Pocket PC. Otherwise, simply use Mobilecore.
The
Pocket PC also implements the FullPath
method, since the Pocket PC OS has the same problem as the Symbian
OS: no relative paths. Perhaps someone can explain to me why Microsoft
left this out?
The
rest of the Pocket PC implementation will be familiar to Win32 coders:
The WinMain starts
to call Tick(), and
updates the screen. A message pump and a WndProc
handle incoming events such as button presses and stylus movement.
These events are then passed to Core
so that the game can use them.
You
can load the Pocket PC version of Mobilecore into Embedded Visual
Tools, which can be downloaded for free from the Microsoft website:
http://www.microsoft.com/mobile/.
The IDE is the same as used in Visual C++, so you'll feel right
at home. You will need to transfer files by hand to your device,
or you can build a nice installer package using one of the available
tools.
Mobilecore
on PC
It's
good to have a PC port of the library for obvious reasons: An application
can be developed more easily on a PC, because the whole edit-compile-run
cycle is much shorter (seconds instead of minutes). Besides that,
there are very good debugging tools available for PC. I really like
the built-in debugger of Visual Studio 6.0, and without it I'm virtually
blind. For the tough-to-find problems and a last-minute leak checking
I use BoundsChecker.
Obviously,
not all bugs can be found by debugging on a PC. One example: x86
CPUs accept byte read and writes on odd memory addresses, while
ARM processors don't allow this. That's not a big deal, but it can
cause a crash in code that works perfectly on the desktop machine.
Other things that can go wrong are path names: Code compiles just
fine if you don't use the FullPath
method, but it will not behave as you intended when you try it on
a Symbian device or Pocket PC.
But
there are more advantages to working on a PC than debugging and
faster development. If a programmer can use a PC to test the application,
he doesn't need to have full-time access to the actual target device.
A key advantage is that the PC can run the application in varying
resolutions so that the game's graphics code can easily be tested
for all target devices. Finally, graphics output can be captured
easily from the PC version. It's even possible to send a PC demo
of your game around.
Fortunately,
the PC version is a piece of cake, especially since the Pocket PC
version is already done. I choose to use a simple bit of GDI code
for graphics output. It's not the best performing code you'll see,
but as the PC only serves as a development and testing platform,
it makes no sense to optimize it any further.
Like
the Pocket PC, the PC version starts in C with a WinMain.
The WinMain instantiates
the Core and passes
events using a message pump.
Using
Mobilecore
To
use Mobilecore for a game project, you simply derive a game class
from the Core class,
and implement the pure virtual methods (see listing 3).
|
|
class MyGame : public Core
{
public:
MyGame();
~MyGame();
bool Tick();
void ButtonUp( int a_Key );
void ButtonDown( int a_Key );
};
|
 |
 |
 |
Listing
3: Minimal declaration of a derived game class.
|
That's
theory, but reality is a bit more complicated. If
your game uses 3D polygonal objects, this is going to do the job
just fine, as vector graphics scale perfectly and will run in any
resolution. For a demo you don't need controls, so you don't need
to worry about stylus input for the P800 (a device that almost completely
lacks hardware buttons).
For
the average game, you will need to take into account some hardware
differences -- most notably the resolution. You can use the Windows
version to test your game on various screen sizes. At Overloaded,
we found that tile-based games can quite easily be adapted for various
resolutions. Often such a game can be left mostly unmodified; the
player will simply see less on smaller displays. Some situations
in the game may need to be tweaked because of this, but in general,
the amount of extra work is limited. When the resolution change
is more drastic (we also develop for J2ME devices with very small
screens), it may be necessary to have multiple tile and sprite sets.
The
"tick" mechanism and the assumption that the game is using
a state-driven approach could also limit the usefulness of the library
for porting existing applications. Whether or not an existing game
can easily be ported to other platforms using Mobilecore depends
on whether or not the game can be changed into a state-driven application
(if the game is not already working this way, of course).
Now
there's one little issue that I didn't mention yet: global variables.
Symbian does not support them. As DLLs can be in ROM or RAM on the
device, the Symbian OS simply crashes on all write operations to
non-static global data. While there are lots of ways to prevent
using global data, in some cases it's just very inconvenient. But
there is a way around this. Symbian allows you to use one
global 32-bit value. It's stored in a memory location pointed to
by Dll::Tls() (which
stands for "thread local storage"). In this variable,
we can store a pointer to a struct
or class that contains
all the global data that we wish to use. Have a look at listing
4:
|
|
struct Globals
{
Overloaded::Engine* m_Engine;
CSymbianContainer* m_System;
Overloaded::MManager* m_MManager;
Overloaded::TManager* m_TManager;
Overloaded::Rasterizer* m_Rasterizer;
};
#ifndef __SYMBIAN32__
extern Globals* DATA;
#else
#define DATA ((Globals*)Dll::Tls())
#endif
|
 |
 |
 |
Listing
4: Global data in Symbian.
|
This
is a snippet from the racing game, Fantom Overdrive. As the
game uses a custom memory manager for fast allocation and recycling
of vertices and other data, I really needed some global data. In
listing 4, the Symbian way of accessing global data is DATA->m_Engine,
which maps to ((Globals*)Dl::Tls())->m_Engine,
while the PC way is more direct.
The
same approach can be used for static data members of classes. If
class Vertex needs a static Engine pointer s_Engine,
just add s_Vertex_Engine
to the Globals struct.
From there on, instead of using s_Engine,
you use DATA->s_Vertex_Engine.
Not perfect, but pretty close.
To
compensate for the ugly globals hack, I will demonstrate how to
use the Symbian device buttons that are not available to all devices.
If you look at the class declaration of the Core for Symbian, you
will see a list of keys that is different from the list of buttons
defined in the CORE.H file. Mobilecore assumes that all devices
have four directional buttons--one "fire" button and two
other buttons. Some devices have fewer buttons, so your game needs
to be prepared for that, as well as the fact that some devices have
many more buttons. Devices such as the N-Gage actually have a full
numeric keypad, which may come in handy in some situations. If you
want to use Symbian-specific code, you can do so by checking for
the __SYMBIAN32__
definition. Likewise, you can check for _WIN32_WCE
when running on a Pocket PC device.
Adding
Functionality
Mobilecore
offers games an easy and platform-independent (though currently
processor-dependent) way of accessing a frame buffer, the stylus,
and hardware buttons. There are some things missing however.
Sound.
Implementing a multi-channel audio system requires an accessible
audio stream. I have implemented this for Pocket PC, Symbian and
PC, and this code will be available shortly.
Communications.
Many (if not all) devices support some form of communication. Pocket
PCs can use infrared, Bluetooth or wi-fi to communicate with each
other; Symbian phones are Bluetooth enabled and are also capable
of infrared communications, in addition to GPRS and GSM data transport.
In order to build multiplayer games it would be interesting to have
some generic way of communicating. Although it's probably too much
to go for device-independent communications (playing a game between
a 7650 and a Pocket PC over Bluetooth would be awesome!), these
days you can't really get away with a game that does not offer some
form of multiplayer gaming.
Vibration,
backlight, and scroll wheels. Some devices allow direct manipulation
of the backlight or the vibration hardware. It would be nice if
Mobilecore were enhanced to supported this, so that a game can use
these features on devices that support it.
Further
Development
I
have created a SourceForge project for Mobilecore at the following
URL:
http://www.sourceforge.com/projects/mobilecore/
Here
you can download the latest version. If you are familiar with one
of the "missing platforms," you are more than welcome
to join in.
As
the current code is only a few weeks old, there is lots of work
to be done. I would really like to support more platforms, but the
existing platforms will need continuous improvement too. The Pocket
PC version could use more diversity (for instance, there are faster
libraries for full-screen frame buffer access than Microsoft's GX).
For
Symbian, there are other issues: For instance, while the stdio
and stdlib functions
are available, they are somewhat hidden in the SDK and documentation,
and for a good reason: The implementation is not without problems.
If you check the code that determines the full path for a given
filename, you'll see that I had to code strstr
myself to prevent problems. Issues such as these need to be identified
and fixed.
I
assume that every platform is going to have its list of issues.
Therefore I have submitted Mobilecore to SourceForge; I hope that
there will be at least one expert for each platform.
Further
Reading
If
you want to know more about mobile games development, you may want
to check out the following links:
Tapwave
developer pages:
http://my.tapwave.com/developers/index.asp
Forum
Nokia:
http://www.forum.nokia.com/main.html
3D
graphics for mobile devices:
http://www.flipcode.com/articles/article_mobilegfx01.shtml
GP32
coding page that makes you want a GP32 badly:
http://www.devrs.com/gp32/
PalmOS
developer community at PalmSource:
http://www.palmsource.com/developers/
Peter
van Sebille's MAME for Symbian with lots of technical information:
http://www.symbian.com/developer/techlib/papers/mame/mamedream.html#MAME.MAME-029
______________________________________________________
|