JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
  Previous Section Next Section

Getting into the Mode of Things

The next step in setting up DirectDraw is probably the coolest of all. Normally, in DOS setting the video mode is fairly reasonable for the basic ROM BIOS modes, but in Windows it's nearly impossible due to the aftershocks of the mode switch. However, with DirectX, it's a snap. One of the main goals of DirectDraw was to make video mode switching trivial and transparent to the programmer. No more VGA/CRT control register programming just to make a single call. Presto—the mode will be set to whatever you desire (if the card can do it, of course).

The function to set the video mode is called SetDisplayMode() and is a method of the IDirectDraw7 interface, or, in C++-speak, IDirectDraw7::SetDisplayMode(). Here's its prototype:

HRESULT SetDisplayMode(DWORD dwWidth,  // width of mode in pixels
               DWORD dwHeight, // height if mode in pixels
               DWORD dwBPP,    // bits per pixel, 8,16,24, etc.
               DWORD dwRefreshRate, // desired refresh, 0 for default
               DWORD dwFlags); // extra flags (advanced) 0 for default

As usual, the function returns DD_OK if successful.

All you should be saying is, "Wow, this is too good to be true!" Have you ever tried to set up a Mode X mode like 320x400 or 800x600 mode? Even if you're successful, good luck trying to render to the video buffer! With this DirectDraw function, you just send the width, height, and color depth, and bam! DirectDraw handles all the idiosyncrasies of whichever video card is plugged in, and if the requested mode can be built, it is. Moreover, the mode is guaranteed to have a linear memory buffer…but more on that later. Take a look at Table 6.3 for a brief refresher on the most commonly used video modes and their color depths.

Table 6.3. Common Video Mode Resolutions
Width Height BPP Mode X
320 200 8 *
320 240 8 *
320 400 8 *
512 512 8,16,24,32  
640 480 8,16,24,32  
800 600 8,16,24,32  
1024 768 8,16,24,32  
1280 1024 8,16,24,32  

Higher resolution modes are available on many cards.

Interestingly enough, you can request any mode you wish. For example, you can choose 400x400, and if the video driver can build it, it will work. However, it's best to stick to the modes listed in Table 6.3 because they are the most common.

TRICK

Actually, there is a Win32 API function to set the video mode that I have used before, but it wreaks havoc on the system and really messes things up.


Referring back to the function, the first three parameters are straightforward, but the last two need a bit of explanation. dwRefreshRate is used to override the video driver's default refresh for the mode you request. Hence, if you request a 320x200 mode, chances are the refresh will be at 70Hz. But with this parameter, you could force it to 60Hz if you wanted to. I would leave the refresh rate alone, to tell you the truth, and simply set the bit to 0 (which indicates to the driver to use the default).

The last parameter, dwFlags, is an extra flags WORD that is a catchall and is of very little use. Currently, it's used as an override so you can use VGA mode 13h for 320x200 instead of Mode X 320x200 via the flag DDSDM_STANDARDVGAMODE. Again, I wouldn't worry about it. If you do write a game that uses 320x200, you can try experimenting with this flag and using VGA mode 13h or Mode X for 320x200 to see which is faster, but the performance difference will be almost negligible. For now, just set dwFlags to 0.

That's enough of the preliminaries. Let's get to switching modes! To switch modes, you must create the DirectDraw object, set the cooperation level, and finally set the display mode, like this:

lpdd->SetDisplayMode(width,height,bpp,0,0);

For example, to create a 640x480 mode in 256 (8-bit) color, you would do this:

lpdd->SetDisplayMode(640,480,8,0,0);

And to set a 800x600 with 16-bit color, you would do this:

lpdd->SetDisplayMode(800,600,16,0,0);

Now, there's a big difference between these two modes that extends further than the mere difference in resolution: the color depth. An 8-bit mode works completely differently than 16-bit, 24-bit, or 32-bit modes. If you'll recall, the previous chapters on Win32/GDI programming covered the topic of palettes extensively (Chapter 3, "Advanced Windows Programming," and Chapter 4, "Windows GDI, Controls, and Last-Minute Gift Ideas"), and the same theory is in force with DirectDraw. That is, when you create an 8-bit mode, you are requesting a palletized mode, and you must also create a palette and fill it with 8.8.8 RGB entries.

On the other hand, if you create a straight RGB mode with color depth 16, 24, or 32 bpp (bits per pixel), you don't have to worry about this step. You can write encoded data directly to the video buffer (when you learn how). At very least, you must learn how to work with DirectDraw palettes (which will be the next topic of discussion). However, before moving on, let's take a look at a complete example of creating a full-screen DirectX application with a resolution of 640x480x8.

DEMO6_2.CPP on the CD and the associated executable do just that. I would show you a figure, but all you would see is a black rectangle because the demo is a full-screen application. However, I can surely show you the code that makes it happen. As usual, I have based the demo on your game console, with the appropriate modifications, and made the DirectX-related changes to the Game_Init() and Game_Shutdown() sections, which are listed here from DEMO6_2.CPP. Take a close look at them and be amazed by the simplicity…

int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
   {
   // error
   return(0);
   } // end if



// set cooperation to full screen
if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
                   DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
                   DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
   {
   // error
   return(0);
   } // end if

// set display mode to 640x480x8
if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,
                  SCREEN_HEIGHT, SCREEN_BPP,0,0)))
   {
   // error
   return(0);
   } // end if


// return success or failure or your own return code here
return(1);

} // end Game_Init

/////////////////////////////////////////////////////////////

int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all your cleanup and shutdown here

// simply blow away the IDirectDraw7 interface
if (lpdd)
   {
   lpdd->Release();
   lpdd = NULL;
   } // end if

// return success or failure or your own return code here
return(1);

} // end Game_Shutdown

At this point, there are two things that you're still missing: controlling the palette (in 256-color modes) and accessing the display buffers. Let's take care of the color problem first.

      Previous Section Next Section
    



    JavaScript EditorAjax Editor     JavaScript Editor