PocketPC: An Introduction
Windows CE is a monsterous mess, and it's frighteningly difficult to use
If you've been reading the trade articles of the past few years, this is probably the impression you got from Microsoft's handheld entries. There are some facts, though, that you might not know. . .
This article is going to explore what exactly is Windows CE, what this PocketPC thing is, some of the technical aspects that make it the finest platform for handheld gaming available today, and how to get started developing for one.
What is Windows CE and What is PocketPC?
Unlike Microsoft's previous efforts at ROM-able Windows, Windows CE is a ground-up rewrite. While it may look more or less like plain old Windows , it is a completely different animal from Windows 3.x, Windows 9x, and Windows NT.
The designers of CE decided early on to focus on portability and small size in the design of CE, and it shows. Making a truly tiny machine based on a Pentium-class processor just wouldn't be practical, because even though there are low-power Pentium-class processors for laptops, shrinking a Pentium machine to the size of a deck of cards and still getting reasonable battery life just wasn't going to happen. Hence, Windows CE was written to work with for alternative processors with very low power consumption, like the StrongARM, SH3/SH4, and MIPS.
Thankfully, though, you don't have to worry about what processor for which you're writing. Much like Microsoft's unsuccessful plans for Windows NT running on every desktop platform, you can write to a standard Windows API and get your application to work on all CE processors with a simple recompile.
. . .and this time, it actually works.
While Windows CE is not locked into any particular form-factor and is capable of running on anything from embedded microcontrollers to cell-phones, two main form-factors have become predominant, the Handheld PC and the PocketPC.
Handheld PC 2000
This version should look instantly familiar. It looks and acts very similarly to the Windows you've come to know and tolerate.
The only major difference is that the applications don't live in nice little overlapping panes. Since the screen is so small, apps automatically grow to the size of the screen, and the title and menubars are combined. Here's what the baby version of Excel looks like on the same machine.
The market for Handheld PC's based on Windows CE unfortunately is in decline. While the platform started strongly a few years ago with high-quality offerings like the Philips Velo, HP Jornada, Sharp Mobilon, and Vadem Clio, only the HP has survived until the release of MS's Handheld PC 2000 software.
In response to the instant success of the Palm Computing platforms, Microsoft intruduced the Palm-size PC. Like the Handheld PC, it started out with several vendors, many of which bailed after low sales, like Uniden and Philips. Despite the technical superiority of hardware like the Casio E-100 series, the Palm-size PC platform was savaged by critics for being overcomplicated and clumsy to use. The standard Windows interface, while it worked well on larger screens, was tight on Handhelds and was downright difficult on a small 240x320 screen.
About a year ago, Microsoft released a new version of the Windows CE interface, redubbed "PocketPC". While internally it was basically the same Windows CE as the earlier versions, the user-interface was retooled to work better on a tiny screen. The start menu was moved to a little icon in the corner. The menubar shrank and moved to the bottom. It took very good advantage of color. Best of all, Microsoft finally made available the baby-office apps that had previously only been available on the Handheld PC's. Critics, on the whole, have been warm to the changes, finding the interface faster and easier to use.
The best way to show the capabilities of the respective devices is to show them side-by-side. Here is a table showing the capabilities of the most popular PocketPC devices on the market. Also shown are a couple of popular Palm devices for comparison.
As you can see, the PocketPC machines are all more expensive than the Palms, but the capabilities of the PocketPC's are disproportionately greater. Numbers, though, can only give you part of the story. Here's a comparison of some of the best of the PocketPC offerings compared with the best color Palm titles.
How Do You Program for PocketPC?
Well, you're in luck. Not only are there some very capable developer tools for PocketPC, they're available for a song. You can purchase Microsoft's eMbedded Visual Tools 3.0 CD from Microsoft for only the cost of shipping and handling. The package includes eMbedded Visual C++, eMbedded Visual Basic, and emulators for the platforms mentioned above.
The tools are very mature and robust. In fact, they're almost identical to their Windows-only brethren, Visual C++ 6.0 and Visual Basic 6.0. The biggest difference is that they do not generate native x86 Windows applications. The C++ compiler cross-compiles to the aforementioned processors, while eMbedded Visual Basic produces files that are interpreted by a VBScript-style interpreter on the target device.
Let's dispense early on with Visual Basic for games, though. Since eMbedded Visual Basic produces programs that are interpreted by the PocketPC's rather rudimentary VBScript interpreter, eMbedded Visual Basic isn't really suitable for games. If you need a form-based data-collector or something to perform field calculations for you, it's ideal. For games, though, it's just not there. Let's concentrate on the eMbedded Visual C++.
How the compiler works
There are two ways to develop an app for PocketPC, and you will very likely be using both methods interchangably.
The first is by compiling your game for a connected device, then uploading, running, and debugging the game over the connection (usually serial). While this sounds complicated, it's actually quite simple. eMbedded Visual C++ works through MS's ActiveSync software, which is the software used to connect your PocketPC to your computer to exchange data with your address book and calendar. If your PocketPC is connected via ActiveSync, you've done all that's necessary to develop for your device. Simply choose the processor that your device has and press the "make" button just as if you were making a standard Windows application. The file will be compiled, linked, and sent over to the device. Press the "run" button, and your app will pop up on the device's screen. Set a breakpoint in your code, and the code will stop when it gets to that point. Examine a variable in memory, and Visual C++ will get the value and show it to you on your main screen. Neat, huh?
As you may have already figured out, though, there is one chief disadvantage to this approach -- speed. While compiling the file and sending it over to the device happens at a reasonable speed, debugging is downright glacial. The device and eMbedded Visual C++ are constantly having to update each other as to the status of your running program. You'll probably want to save debugging on the device as a last resort to fix bugs that don't show up under the next method -- compiling for the PocketPC emulator.
The second method is to develop for the on-screen PocketPC emulator. Calling it an emulator, though, is a bit of a misnomer. Rather than make processor-emulators for the various processors out there, MS simply built a version of Windows CE that runs on an x86 processor. To compile for the emulator, you set the target processor as the x86 CE Emulator, press the "make" button, and eMbedded Visual C++ will generate a Windows CE app that runs on the x86 processor. Pressing the "run" button will then run your app in the on-screen Windows CE emulator.
The principal advantage to this approach is speed. Speed speed speed. Using the on-screen emulator, you can run an application under the debugger and it will run just as quickly as if you were debugging a native Windows application. Copying the app to the on-screen emulator and running is almost instantaneous. Developing an app for the on-screen emulator will make you feel right at home if you're used to developing standard Windows apps under Visual C++ 6.0.
There are plenty of disadvantages, though, to this approach. For one, you're compiling for a processor that simply doesn't exist in the PocketPC world. If a particular device has some picadillos germaine to its processor, you won't see them when it runs on the emulator. Also, the emulator takes on the capabilities of the compiling machine, so you'll likely be developing your app on a 24-bit screen even though there are no PocketPC's with 24-bit screens. Furthermore, your emulated app will likely be running much faster emulated than on the device, so you won't get a good feel for how your game plays if you develop solely for the emulator. Finally, the emulator only runs on Windows NT or Windows 2000 for reasons that will be clear later. If you have Windows 95/98/ME, you're stuck with developing on the connected device.
Most PocketPC developers quickly find that they need to work between the two different methods to develop a PocketPC game. For the bulk of development, the on-screen emulator is the way to go. It's a great way to get your app up and running quickly, and debugging is a breeze. From time to time, though, you'll need to compile on the device so you can ensure that the graphics look right, the game is playing at a reasonable speed, and no bugs are creeping in that aren't showing up on the emulator. Thankfully, switching between one approach and another is as simple as choosing the target processor on the toolbar and recompiling.
The PocketPC API
If this all looks great, and you're chomping at the bit to convert your large-scale DirectDraw-based isometric RPG title to the PocketPC, there's something you need to know.
The PocketPC API is different from the Win32 API
Sorry to throw a bucket of cold water on your plans, but if you have grand designs on simply recompiling your code and having it work, it's not going to happen that easily. A significant chunk of the Win32 API functions (around 90% of 'em, actually) aren't there.
Hey, where's GlobalAlloc?
Operating systems are evolutionary things. Every year a new version comes out with new capabilities, some of which supercede existing capabilities. The OS makers, though, often must leave antiquated function calls in place to keep from breaking old apps. Since there weren't going to be any old CE apps, the designers went through the Win32 API with a fine-toothed comb to prune it down to its bare essentials -- a library that would still allow you to create powerful apps, but without supporting a lot of antiquated function calls. Hence, if you're looking for AddAtom() or GetWindowWord(), you won't find them.
After dumping the dead wood, the designers went through the list of similar, yet redundant functions. For the most part, if there existed several functions that did a similar job, they just kept the one or two that could best cover the capabilities of the rest. Hence, MoveTo() and LineTo() are gone, but PolyLine() is still there. CreateFont() is gone, but CreateFontIndirect() is still there. DrawText() was better than TextOut(), so DrawText() got to stay. You get the idea. Just be prepared, when developing a PocketPC app, to hunt for updated versions of some of your favorite API functions.
You can ignore Unicode no longer
Something else you're going to have to get used to is text-handling. Since Unicode is the way of the world, and supporting both ANSI and Unicode would take up more space than necessary, ANSI strings got the boot. All of the PocketPC functions that take strings are expecting Unicode strings. So don't type:
MessageBox (hWnd, "This is my first CE app", "Hello World", MB_OK);
You'll just upset your compiler. What it wants to see is:
MessageBox (hWnd, TEXT("This is my first CE app"), TEXT("Hello World"), MB_OK);
The TEXT-macro simply converts a string at compile-time to unicode format. This goes for every hard-coded string in your application, from window-class-names to filenames you pass to the file-handling commands. There are Unicode equivalents for all of your favorite string-handling functions, so don't get too upset. Just kiss the venerable old char * goodbye.
Direct3D, DirectDraw, DirectInput, DirectPlay, and OpenGL
PocketPC doesn't support them. In fact, the API functions that aren't part of the Kernel, Window, and GDI modules of Windows probably aren't there. While some extensions like Winsock are still around (supporting IR communication, cool eh?), many of the latter-day add-ons to Windows are nowhere to be found.
Don't dispair, though. There a couple of game-related technologies available that will help you ease the pain of working for the platform.
While DirectX isn't there, you're not completely out of luck. There are some technologies that'll ease the pain of losing DirectX.
GAPI, formally GameX, is a technology that MS licensed that allows direct framebuffer access for games in a reasonably portable way. It's without-a-doubt the fastest way to throw pixels on the screen, but it's got a couple of drawbacks.
GAPI is simple. It's only ten function calls. After initializing GAPI with GXOpenDisplay(), you can call GXBeginDraw() to get a pointer to the framebuffer. GXGetDisplayProperties() returns a structure containing the properties of the display, including bits per pixel, width, height, X pitch, and Y pitch. The pitch values specify the distance between pixel values in the buffer, because a framebuffer is not necessarily a 240x320 array of 16-bit values. It's up to the hardware maker how the video memory is organized.
In addition to framebuffer access, GAPI gives you a relatively platform-neutral way of accessing the PocketPC's controls. This is important because while some handhelds like the Casio and the iPaq have nice little direction-pads, some like the new HP PocketPC decided to clone tha Palm's horrible four-horizontal-keys layout. GXGetDefaultKeys() returns a struct containing the standard key-values that PocketPC supports, so you can easily check to see if a key is down.
While GAPI's strengths are that it is very simple and does the job it sets out to do, it has a couple of weaknesses. First off, it's propriatary. While there are GAPI DLL's available for Casio, Compaq, and HP, there aren't any such DLL's available for other models or form-factors, and you're beholden to Microsoft if any new PocketPC models come out.
Another problem with GAPI is that direct framebuffer access precludes all of the nice window commands. If you want to draw a line, some text, or stretch a bitmap, you're on your own.
Finally, GAPI doesn't run on the emulator, which gets rid of some of the advantages of developing on-screen as mentioned in the previous article. Thankfully, though, an intrepid hacker wrote a GAPI DLL that indeed works on the emulator. It is available here.
The DIBSection API and CEAnim
If you don't need to throw pixels at the screen at the highest speed possible, and you want very good speed without worrying about what new platforms are coming out and whether or not GAPI will support them, you should look at the Win32 DIBSection API. It's been around since Windows 95, and it works.
DIBSections are weird birds. Back in the days of Windows 3.1, there were only two different ways to handle bitmaps, DDB's and DIB's. DDB's (Device Dependent Bitmaps) are owned by the video driver and are in whatever format the driver prefers. They are very fast to display but have one gigantic drawback -- you can't change the bits once you've created the bitmap. If you want to change the bits, you need to create a new bitmap, which make it far less than optimal for displaying frames of animation. The second method is the Device Independent Bitmap. A DIB's memory is owned by your application, but drawing the bitmap to the screen requires the video driver to convert the bitmap to screen format, which makes displaying them much slower than DDB's.
In the latter days of Windows 3.1, Microsoft created the much-maligned WinG. WinG added a third bitmap type that combined the best of both worlds. You could modify the bits directly, and you could display them to the screen quickly. Several console games were ported using WinG, like Earthworm Jim and a few other scrolling platform-games.
The WinG API survived into Windows 95 as the DIBSection API, and it still exists today. Using CreateDIBSection(), you can create a buffer of memory that's shared between the application and video driver. You can change the bits as necessary and blit the buffer to the screen very quickly using the standard old BitBlt() command.
CEAnim is an extensive class library for Windows CE by Random Software (www.randomly.com). It leverages the DIBSection API to the hilt to provide all kinds of animation effects, including sprite animation, alpha blending, dirty rectangle management, and palette management. On the whole, it's much more more extensive and high-level than GAPI.
In addition to graphics, CEAnim includes a library of common data structures and memory management functions. Best of all, though, is that it addresses a problem caused by the loss of DirectSound -- wave mixing. There's a sound class that can play multiple sounds at once so you don't have to cripple the sounds in your game.
It's certainly worth a look. Download it at ftp://www.randomly.com/src/ceanim_src.zip. If anything, check out the author's CE offerings at the web address above to see the kind of things you can do.
The DOOM and Quake Engines
Direct3D and OpenGL don't exist for PocketPC, but you're not out of luck if you're looking for 3D that fits in your pocket. Both Doom and Quake 1 have been ported to PocketPC, and you can use them to develop your own projects. The engines for both Doom and Quake are both freely available and use the Gnu Public License, so you can freely use them in your own projects -- even commercial ones!
PocketPC's are cool. It's easy to develop for them. The development tools are robust and very inexpensive. While the whole of the Win32 API isn't there, there's enough to get around. And there are a few technologies that will help you develop games that rival what you see on the desktop.
PocketPC Development Resources
Games (be sure to check out your competition)