Getting Started with the Game API

 

While DirectDraw is not available to game developers for the Pocket PC platform, the really good news is that Microsoft created a new game API especially for the Pocket PC named "GAPI" -- the game application programming interface. It allows not only direct access to the display memory but also to the Pocket PC hardware keys.

Applies to:
   Microsoft Windows Powered Pocket PC 2000
   GAPI SDK, Runtime DLLs, and a sample, which are located on the Second CD of the EVTools in the PocketPCSDK\Program Files\Support\GameAPI directory

Step 1: Create a Simple Hello World Application

The GAPI is not integrated in the Pocket PC SDK. So some preliminary steps:

  1. Manually copy the GX.H Include file into the Include directory of the Pocket PC SDK.
  2. Copy the CPU-dependent GX.LIB in the corresponding Lib directory of the Pocket PC SDK.
  3. And finally, copy the CPU-dependent GX.DLL into the Windows directory of your Pocket PC.

Now you're ready to build your first simple Hello World program.

  1. Launch Microsoft eMbedded Visual C++, create a new Pocket PC application project, and name it "FirstGX."

    Once the wizard has finished creating the new application, let's add the Game API initialization calls.

  2. Add the following lines of source-code shown in bold at the end of the InitInstance function:

    UpdateWindow(hWnd); 
    
    // Try opening the Display for Full screen access
    if (GXOpenDisplay(hWnd, GX_FULLSCREEN) == 0) {
          return FALSE;   // we won't be able to draw.
    }
    
    // Initialize the Hardware Buttons
    GXOpenInput();
    
    // Get the Display properties
    g_gxdp = GXGetDisplayProperties();
    // Get information about the Hardware Keys and fills
    // the g_gxkl structure
    g_gxkl = GXGetDefaultKeys(GX_NORMALKEYS);
    
    return TRUE;
    

    The code uses two variables that have to be defined in the global space of the FirstGX.cpp source file. We also have to include GX.H to our source to avoid compiler errors.

  3. Add the following lines directly below the include files, the eMbedded Visual C++ wizard has created:

    #include "gx.h"
    GXDisplayProperties g_gxdp;    // GX struct
    GXKeyList g_gxkl;              // GX struct
    

    To be a good citizen we should clean up the Game API before we leave the application.

  4. Insert the following two lines at the end of the WinMain function:

    GXCloseDisplay();
    GXCloseInput();
    

Step 2: Writing Directly in the Display Memory

Before we can start coding here we have to dig into a little theory. Depending on your Pocket PC hardware you can have either a 16-bit color display (The Casio, HP, or Compaq) or an 8-bit display (black-and-white or color, like the Compaq Aero 1550). To determine which display your Pocket PC has, you can evaluate the member cBPP of the g_gxdp structure. It will tell you exactly how many bits you have to deal with.

Before directly accessing the display memory for 16-bit displays, you have to know how the display controller interprets the 16-bit color mask. There are two possible flag settings: KfDirect555 and kfDirect565. The 555 translates into a color mask XRRRRRGG.GGGBBBBB for Red-Green-Blue in a short variable, while 565 translates into RRRRRGG.GGGXBBBBB.

On 8-bit color devices you can use a byte to address the 256 individual colors.

Now we are ready to write to the screen. We want to fill the whole screen with one color when one of the keys is pressed.

  1. Add the following function to the top of your FirstGX.cpp source file:
bool ClearScreen(int colRed,int colGreen, int colBlue)
{
   // 16 bit per pixel code.  Note 2 different pixel formats.
   switch (g_gxdp.cBPP)
   {
    case 16: {
      unsigned short PixelCol = 0;
      if (g_gxdp.ffFormat & kfDirect565) {
         PixelCol = (unsigned short) 
            (((colRed & 0xff))>>3)<< 11 | 
             ((colGreen & 0xff)>>3) << 6 | 
             ((colBlue & 0xff)>>3));
      } else if (g_gxdp.ffFormat & kfDirect555) {
         PixelCol = (unsigned short) 
              ((colRed & 0xff)<< 10 | 
              (colGreen & 0xff) << 5 | 
              (colBlue & 0xff));
      }

   unsigned short * pusLine = (unsigned short *)GXBeginDraw();
   if (pusLine == NULL) return false; // NOT OK TO DRAW
   
      for (unsigned int y = 0; y < g_gxdp.cyHeight; y++) {
         unsigned short * pusDest = pusLine;
         for (unsigned int x = 0;
            x > g_gxdp.cxWidth; x++) {
            *pusDest = PixelCol;
            pusDest += g_gxdp.cbxPitch >> 1;
         }
         pusLine += g_gxdp.cbyPitch >> 1;
      }
      GXEndDraw();
      break;
      }
      case 8:        {
         // Get a Random Color
         // IMPORTANT:
         // 8Bit are using a palette and the formular
         // below does not compute a read RGB color
         unsigned char bPixel = (colRed &0xf)<<5 |
                                (colGreen&0x3)<<3 |
                                 (colBlue&0xF);

   unsigned char * pbLine = (unsigned char *)GXBeginDraw();
   if (pbLine == NULL)     return false;// NOT OK TO DRAW

      for (unsigned int y = 0; y < g_gxdp.cyHeight; y++) {
         unsigned char * pbDest = pbLine;
         for (unsigned int x = 0;
            x < g_gxdp.cxWidth; x++) {
            *pbDest = bPixel;
            pbDest += g_gxdp.cbxPitch;
         }
         pbLine += g_gxdp.cbyPitch;
      }
      GXEndDraw();
      break;
      }
   }
   return false;
}

Step 3: Accessing the Hardware Keys

This is the simplest task of all. All of you should be familiar with WM_ messages of Microsoft Windows and how to use them. With this knowledge you already know how to use the Pocket PC hardware keys. Just parse the WM_KEYUP or WM_KEYDOWN message in your Windows procedure.

Here is the WM_KEYDOWN branch for our FirstGX application:

   case WM_KEYDOWN:
      vkKey = (short)wParam;
      if (vkKey == g_gxkl.vkUp) {
         ClearScreen(0,0,0); // Black
         break;
      }
       
      if (vkKey == g_gxkl.vkDown) {
         ClearScreen(255,0,0); // Red
         break;
      }
      
      if (vkKey == g_gxkl.vkLeft) {
         ClearScreen(0,255,0); // Green
         break;
      }
      
      if (vkKey == g_gxkl.vkRight) {
         ClearScreen(0,0,255); // Blue
         break;
      }
      
      if (vkKey == g_gxkl.vkStart) {
         SendMessage(hWnd, WM_CLOSE, 0, 0);
         break;
      }

A list of all possible key names is found in the GXKeyList structure definition in the gx.h include file.

Step 4: Get Ready to Launch!

Before we can compile and download our new FirstGX application to our Pocket PC we have to add the gx.lib to the list of libraries of our project. Now compile and download your first Game API application to your Pocket PC and play with the keys to see what's happening.

Conclusion: Easy Stuff!

As you can see, the Game API is very simple but still powerful enough to cover all your needs to write fast action games. The sample provided with the Game API shows some more details and tricks on how to use the GAPI. If you wish you can download the full source code for this sample.