home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / Source / GPCHAP11 / PROG11_3.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-27  |  18.4 KB  |  654 lines

  1. // PROG11_3.CPP - the trench; color rotation demo
  2.  
  3. // INCLUDES ///////////////////////////////////////////////
  4. #define WIN32_LEAN_AND_MEAN  
  5. #define INITGUID
  6.  
  7. #include <windows.h>   // include important windows stuff
  8. #include <windowsx.h> 
  9. #include <mmsystem.h>
  10. #include <iostream.h> // include important C/C++ stuff
  11. #include <conio.h>
  12. #include <stdlib.h>
  13. #include <malloc.h>
  14. #include <memory.h>
  15. #include <string.h>
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <io.h>
  20. #include <fcntl.h>
  21.  
  22. #include <ddraw.h>  // directX includes
  23.  
  24. // DEFINES ////////////////////////////////////////////////
  25.  
  26. // defines for windows 
  27. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  28.  
  29. #define WINDOW_WIDTH  640         // size of window
  30. #define WINDOW_HEIGHT 480
  31. #define SCREEN_WIDTH  640         // size of screen
  32. #define SCREEN_HEIGHT 480
  33. #define SCREEN_BPP    8          // bits per pixel
  34.  
  35. #define BITMAP_ID     0x4D42      // universal id for a bitmap
  36.  
  37. // MACROS /////////////////////////////////////////////////
  38.  
  39. // these read the keyboard asynchronously
  40. #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  41. #define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  42.  
  43. // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
  44. #define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
  45.  
  46. // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
  47. #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
  48.  
  49.  
  50. // TYPES //////////////////////////////////////////////////
  51.  
  52. typedef unsigned short USHORT;
  53. typedef unsigned short WORD;
  54. typedef unsigned char  UCHAR;
  55. typedef unsigned char  BYTE;
  56.  
  57. // container structure for bitmaps .BMP file
  58. typedef struct BITMAP_FILE_TAG
  59.         {
  60.         BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  61.         BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  62.         PALETTEENTRY     palette[256];      // we will store the palette here
  63.         UCHAR            *buffer;           // this is a pointer to the data
  64.  
  65.         } BITMAP_FILE, *BITMAP_FILE_PTR;
  66.  
  67. // PROTOTYPES /////////////////////////////////////////////
  68.  
  69. // game console
  70. int Game_Init(void *parms=NULL);
  71. int Game_Shutdown(void *parms=NULL);
  72. int Game_Main(void *parms=NULL);
  73.  
  74. // blitmap functions
  75. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  76. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  77. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  78.  
  79. // color animation fx
  80. void Blink_Em(int r_rate,int g_rate,int b_rate, int r_i, int g_i, int b_i); 
  81. void Rotate_Colors(LPDIRECTDRAWPALETTE pal,int start_index, int colors);
  82.  
  83. // GLOBALS ////////////////////////////////////////////////
  84.  
  85. HWND main_window_handle = NULL; // save the window handle
  86. HINSTANCE main_instance = NULL; // save the instance
  87. char buffer[80];                // used to print text
  88.  
  89. LPDIRECTDRAW7        lpdd         = NULL;  // dd object
  90. LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;  // dd primary surface
  91. LPDIRECTDRAWSURFACE7 lpddsback    = NULL;  // dd back surface
  92. LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // a pointer to the created dd palette
  93. PALETTEENTRY         palette[256];         // color palette
  94. DDSURFACEDESC2       ddsd;                 // a direct draw surface description struct
  95. DDSCAPS2             ddscaps;              // a direct draw surface capabilities struct
  96. HRESULT              ddrval;               // result back from dd calls
  97. UCHAR                *primary_buffer = NULL; // primary video buffer
  98. BITMAP_FILE          bitmap16bit,            // a 16 bit bitmap file
  99.                      bitmap8bit;             // a 8 bit bitmap file
  100.  
  101. // FUNCTIONS //////////////////////////////////////////////
  102.  
  103. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  104. {
  105. // this function opens a bitmap file and loads the data into bitmap
  106.  
  107. int file_handle,  // the file handle
  108.     index;        // looping index
  109.  
  110. UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
  111. OFSTRUCT file_data;        // the file data information
  112.  
  113. // open the file if it exists
  114. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  115.    return(0);
  116.  
  117. // now load the bitmap file header
  118. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  119.  
  120. // test if this is a bitmap file
  121. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  122.    {
  123.    // close the file
  124.    _lclose(file_handle);
  125.  
  126.    // return error
  127.    return(0);
  128.    } // end if
  129.  
  130. // now we know this is a bitmap, so read in all the sections
  131.  
  132. // first the bitmap infoheader
  133.  
  134. // now load the bitmap file header
  135. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  136.  
  137. // now load the color palette if there is one
  138. if (bitmap->bitmapinfoheader.biBitCount == 8)
  139.    {
  140.    _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
  141.  
  142.    // now set all the flags in the palette correctly and fix the reversed 
  143.    // BGR RGBQUAD data format
  144.    for (index=0; index < 256; index++)
  145.        {
  146.        // reverse the red and green fields
  147.        int temp_color = bitmap->palette[index].peRed;
  148.        bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
  149.        bitmap->palette[index].peBlue = temp_color;
  150.        
  151.        // always set the flags word to this
  152.        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
  153.        } // end for index
  154.  
  155.     } // end if
  156.  
  157. // finally the image data itself
  158. _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
  159.  
  160. // now read in the image, if the image is 8 or 16 bit then simply read it
  161. // but if its 24 bit then read it into a temporary area and then convert
  162. // it to a 16 bit image
  163.  
  164. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)
  165.    {
  166.    // allocate the memory for the image
  167.    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  168.       {
  169.       // close the file
  170.       _lclose(file_handle);
  171.  
  172.       // return error
  173.       return(0);
  174.       } // end if
  175.  
  176.    // now read it in
  177.    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
  178.  
  179.    } // end if
  180. else
  181.    {
  182.    // this must be a 24 bit image, load it in and convert it to 16 bit
  183. //   printf("\nconverting 24 bit image...");
  184.  
  185.    // allocate temporary buffer
  186.    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  187.       {
  188.       // close the file
  189.       _lclose(file_handle);
  190.  
  191.       // return error
  192.       return(0);
  193.       } // end if
  194.    
  195.    // allocate final 16 bit storage buffer
  196.    if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight)))
  197.       {
  198.       // close the file
  199.       _lclose(file_handle);
  200.  
  201.       // release working buffer
  202.       free(temp_buffer);
  203.  
  204.       // return error
  205.       return(0);
  206.       } // end if
  207.  
  208.    // now read it in
  209.    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);
  210.  
  211.    // now convert each 24 bit RGB value into a 16 bit value
  212.    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
  213.        {
  214.        // extract RGB components (note they are in memory BGR)
  215.        // also, assume 5.6.5 format, so scale appropriately
  216.        UCHAR red    = (temp_buffer[index*3 + 2] >> 3), // 5 bits
  217.              green  = (temp_buffer[index*3 + 1] >> 2), // 6 bits, change to 3 for 5 bits
  218.              blue   = (temp_buffer[index*3 + 0] >> 3); // 5 bits
  219.  
  220.        // build up 16 bit color word assume 5.6.5 format
  221.        USHORT color = _RGB16BIT565(red,green,blue);
  222.  
  223.        // write color to buffer
  224.        ((USHORT *)bitmap->buffer)[index] = color;
  225.  
  226.        } // end for index
  227.  
  228.    // finally write out the correct number of bits
  229.    bitmap->bitmapinfoheader.biBitCount=16;
  230.  
  231.    } // end if
  232.  
  233. #if 0
  234. // write the file info out 
  235. printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
  236.         filename,
  237.         bitmap->bitmapinfoheader.biSizeImage,
  238.         bitmap->bitmapinfoheader.biWidth,
  239.         bitmap->bitmapinfoheader.biHeight,
  240.         bitmap->bitmapinfoheader.biBitCount,
  241.         bitmap->bitmapinfoheader.biClrUsed,
  242.         bitmap->bitmapinfoheader.biClrImportant);
  243. #endif
  244.  
  245. // close the file
  246. _lclose(file_handle);
  247.  
  248. // flip the bitmap
  249. Flip_Bitmap(bitmap->buffer, 
  250.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  251.             bitmap->bitmapinfoheader.biHeight);
  252.  
  253. // return success
  254. return(1);
  255.  
  256. } // end Load_Bitmap_File
  257.  
  258. ///////////////////////////////////////////////////////////
  259.  
  260. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  261. {
  262. // this function releases all memory associated with "bitmap"
  263. if (bitmap->buffer)
  264.    {
  265.    // release memory
  266.    free(bitmap->buffer);
  267.  
  268.    // reset pointer
  269.    bitmap->buffer = NULL;
  270.  
  271.    } // end if
  272.  
  273. // return success
  274. return(1);
  275.  
  276. } // end Unload_Bitmap_File
  277.  
  278. ///////////////////////////////////////////////////////////
  279.  
  280. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  281. {
  282. // this function is used to flip upside down .BMP images
  283.  
  284. UCHAR *buffer; // used to perform the image processing
  285. int index;     // looping index
  286.  
  287. // allocate the temporary buffer
  288. if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
  289.    return(0);
  290.  
  291. // copy image to work area
  292. memcpy(buffer,image,bytes_per_line*height);
  293.  
  294. // flip vertically
  295. for (index=0; index < height; index++)
  296.     memcpy(&image[((height-1) - index)*bytes_per_line],
  297.            &buffer[index*bytes_per_line], bytes_per_line);
  298.  
  299. // release the memory
  300. free(buffer);
  301.  
  302. // return success
  303. return(1);
  304.  
  305. } // end Flip_Bitmap
  306.  
  307. ///////////////////////////////////////////////////////////
  308.  
  309. void Rotate_Colors(LPDIRECTDRAWPALETTE pal,  
  310.                    int start_index, int colors)
  311. {
  312. // this function rotates the color between start and end
  313.  
  314. PALETTEENTRY work_pal[256]; // working palette
  315.  
  316. // get the color palette
  317. pal->GetEntries(0,start_index,colors,work_pal);
  318. // shift the colors
  319. pal->SetEntries(0,start_index+1,colors-1,work_pal);
  320. // fix up the last color
  321. pal->SetEntries(0,start_index,1,&work_pal[colors - 1]);
  322.  
  323. } // end Rotate_Colors
  324.  
  325. ///////////////////////////////////////////////////////////
  326.  
  327. void Blink_Em(int r_rate, // rate of red blink in cycles
  328.        int g_rate,  // rate of green blink in cycles
  329.        int b_rate,  // rate of blue blink in cycles
  330.        int r_i, int g_i, int b_i) // indices of colors
  331. {
  332. // this is a self contained autonomous function
  333. // define colors
  334. static PALETTEENTRY black={0,0,0,PC_NOCOLLAPSE},
  335.                     red   = {255,0,0,PC_NOCOLLAPSE},
  336.                     green = {0,255,0,PC_NOCOLLAPSE},
  337.                     blue  = {0,0,255,PC_NOCOLLAPSE};
  338. // state variables
  339. static int red_count   = 0,
  340.            green_count = 0,
  341.            blue_count  = 0,
  342.            red_state   = -1,
  343.            blue_state  = -1,
  344.            green_state = -1;
  345.  
  346. // run algoroithm
  347. // red
  348. if (++red_count>=r_rate)
  349.    {
  350.    // toggle state of red light
  351.    red_state=-red_state;
  352.    red_count = 0; 
  353.  
  354.    // change color entry
  355.    if (red_state==1)
  356.       lpddpal->SetEntries(0,r_i,1,&red);
  357.    else
  358.       lpddpal->SetEntries(0,r_i,1,&black);
  359.    } // end if 
  360.  
  361. // green
  362. if (++green_count>=g_rate)
  363.    {
  364.    // toggle state of green light
  365.    green_state=-green_state;
  366.    green_count = 0;
  367.  
  368.    // change color entry
  369.    if (green_state==1)
  370.       lpddpal->SetEntries(0,g_i,1,&green);
  371.    else
  372.       lpddpal->SetEntries(0,g_i,1,&black);
  373.    } // end if 
  374.  
  375. // blue
  376. if (++blue_count>=b_rate)
  377.    {
  378.    // toggle state of blue light
  379.    blue_state=-blue_state;
  380.    blue_count = 0;
  381.  
  382.    // change color entry
  383.    if (blue_state==1)
  384.       lpddpal->SetEntries(0,b_i,1,&blue);
  385.    else
  386.       lpddpal->SetEntries(0,b_i,1,&black);
  387.    } // end if 
  388.  
  389. } // end Blink_Em
  390.  
  391. ///////////////////////////////////////////////////////////
  392.  
  393. LRESULT CALLBACK WindowProc(HWND hwnd, 
  394.                             UINT msg, 
  395.                             WPARAM wparam, 
  396.                             LPARAM lparam)
  397. {
  398. // this is the main message handler of the system
  399. PAINTSTRUCT    ps;           // used in WM_PAINT
  400. HDC            hdc;       // handle to a device context
  401.  
  402. // what is the message 
  403. switch(msg)
  404.     {    
  405.     case WM_CREATE: 
  406.         {
  407.         // do initialization stuff here
  408.         return(0);
  409.         } break;
  410.  
  411.     case WM_PAINT:
  412.          {
  413.          // start painting
  414.          hdc = BeginPaint(hwnd,&ps);
  415.  
  416.          // end painting
  417.          EndPaint(hwnd,&ps);
  418.          return(0);
  419.         } break;
  420.  
  421.     case WM_DESTROY: 
  422.         {
  423.         // kill the application            
  424.         PostQuitMessage(0);
  425.         return(0);
  426.         } break;
  427.  
  428.     default:break;
  429.  
  430.     } // end switch
  431.  
  432. // process any messages that we didn't take care of 
  433. return (DefWindowProc(hwnd, msg, wparam, lparam));
  434.  
  435. } // end WinProc
  436.  
  437. // WINMAIN ////////////////////////////////////////////////
  438.  
  439. int WINAPI WinMain(    HINSTANCE hinstance,
  440.                     HINSTANCE hprevinstance,
  441.                     LPSTR lpcmdline,
  442.                     int ncmdshow)
  443. {
  444.  
  445. WNDCLASS winclass;    // this will hold the class we create
  446. HWND     hwnd;        // generic window handle
  447. MSG         msg;        // generic message
  448. HDC      hdc;       // generic dc
  449. PAINTSTRUCT ps;     // generic paintstruct
  450.  
  451. // first fill in the window class stucture
  452. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  453.                           CS_HREDRAW | CS_VREDRAW;
  454. winclass.lpfnWndProc    = WindowProc;
  455. winclass.cbClsExtra        = 0;
  456. winclass.cbWndExtra        = 0;
  457. winclass.hInstance        = hinstance;
  458. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  459. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  460. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  461. winclass.lpszMenuName    = NULL; 
  462. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  463.  
  464. // register the window class
  465. if (!RegisterClass(&winclass))
  466.     return(0);
  467.  
  468. // create the window, note the use of WS_POPUP
  469. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  470.                           "WinX Game Console",     // title
  471.                           WS_POPUP | WS_VISIBLE,
  472.                            0,0,       // x,y
  473.                           WINDOW_WIDTH,  // width
  474.                           WINDOW_HEIGHT, // height
  475.                           NULL,       // handle to parent 
  476.                           NULL,       // handle to menu
  477.                           hinstance,// instance
  478.                           NULL)))    // creation parms
  479. return(0);
  480.  
  481. // hide the mouse
  482. ShowCursor(FALSE);
  483.  
  484. // save the window handle and instance in a global
  485. main_window_handle = hwnd;
  486. main_instance      = hinstance;
  487.  
  488. // perform all game console specific initialization
  489. Game_Init();
  490.  
  491. // enter main event loop
  492. while(1)
  493.     {
  494.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  495.         { 
  496.         // test if this is a quit
  497.         if (msg.message == WM_QUIT)
  498.            break;
  499.     
  500.         // translate any accelerator keys
  501.         TranslateMessage(&msg);
  502.  
  503.         // send the message to the window proc
  504.         DispatchMessage(&msg);
  505.         } // end if
  506.     
  507.     // main game processing goes here
  508.     Game_Main();
  509.  
  510.     } // end while
  511.  
  512. // shutdown game and release all resources
  513. Game_Shutdown();
  514.  
  515. // return to Windows like this
  516. return(msg.wParam);
  517.  
  518. } // end WinMain
  519.  
  520. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  521.  
  522. int Game_Init(void *parms)
  523. {
  524. // this function is where you do all the initialization 
  525. // for your game
  526.  
  527. // create object and test for error
  528. if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK)
  529.    return(0);
  530.  
  531. // set cooperation level to windowed mode normal
  532. if (lpdd->SetCooperativeLevel(main_window_handle,
  533.            DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | 
  534.            DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)
  535.     return(0);
  536.  
  537. // set the display mode
  538. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)!=DD_OK)
  539.    return(0);
  540.  
  541. // Create the primary surface
  542. memset(&ddsd,0,sizeof(ddsd));
  543. ddsd.dwSize         = sizeof(ddsd);
  544. ddsd.dwFlags        = DDSD_CAPS;
  545. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  546.  
  547. if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
  548.    return(0);
  549.  
  550. // create and attach palette
  551.  
  552. // create palette data
  553. // first clear out all the entries, defensive programming
  554. memset(palette,0,256*sizeof(PALETTEENTRY));
  555.  
  556. // create a R,G,B,GR gradient palette
  557. for (int index=0; index<256; index++)
  558.     {
  559.     // set flags
  560.     palette[index].peFlags = PC_NOCOLLAPSE;
  561.     } // end for index
  562.  
  563. // now create the palette object
  564. if (lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256,
  565.                          palette,&lpddpal,NULL)!=DD_OK)
  566.    return(0);
  567.  
  568. // attach the palette to the primary
  569. if (lpddsprimary->SetPalette(lpddpal)!=DD_OK)
  570.    return(0);
  571.  
  572. // now load the 8 bit color bitmap
  573. Load_Bitmap_File(&bitmap8bit, "ROTATE8.BMP");
  574.  
  575. // now load the palette into the directdraw
  576. lpddpal->SetEntries(0,0,256,bitmap8bit.palette);
  577.  
  578. // set up the surface description to lock the surface
  579. memset(&ddsd,0,sizeof(ddsd)); 
  580. ddsd.dwSize = sizeof(ddsd);
  581.  
  582. // return success
  583. return(1);
  584.  
  585. } // end Game_Init
  586.  
  587. ///////////////////////////////////////////////////////////
  588.  
  589. int Game_Shutdown(void *parms)
  590. {
  591. // this function is where you shutdown your game and
  592. // release all resources that you allocated
  593.  
  594. // first release the primary surface
  595. if (lpddsprimary!=NULL)
  596.    lpddsprimary->Release();
  597.        
  598. // release the directdraw object
  599. if (lpdd!=NULL)
  600.    lpdd->Release();
  601.  
  602. // delete the bitmap 
  603. Unload_Bitmap_File(&bitmap8bit);
  604.  
  605. // return success
  606. return(1);
  607. } // end Game_Shutdown
  608.  
  609. ///////////////////////////////////////////////////////////
  610.  
  611. int Game_Main(void *parms)
  612. {
  613. // this is the workhorse of your game it will be called
  614. // continuously in real-time this is like main() in C
  615. // all the calls for you game go here!
  616.  
  617. // check of user is trying to exit
  618. if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
  619.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  620.  
  621. // lock the primary surface, note in a real game you would
  622. lpddsprimary->Lock(NULL,&ddsd, 
  623.                    DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
  624.  
  625. // get video pointer
  626. primary_buffer = (UCHAR *)ddsd.lpSurface;
  627.  
  628. // copy each bitmap line into primary buffer 
  629. // taking into consideration non-linear video 
  630. // cards and the memory pitch lPitch
  631. for (int y=0; y < SCREEN_HEIGHT; y++)
  632.     {
  633.     // copy the line
  634.     memcpy(&primary_buffer[y*ddsd.lPitch], // dest address
  635.            &bitmap8bit.buffer[y*SCREEN_WIDTH],   // src address
  636.            SCREEN_WIDTH);                        // bytes to copy
  637.     } // end for y
  638.  
  639. // unlock the surface
  640. lpddsprimary->Unlock(NULL);
  641.  
  642. // rotate the colors they are entries 252-254
  643. Rotate_Colors(lpddpal,252,3);
  644.  
  645. // wait a sec
  646. Sleep(100);
  647.  
  648. // return success
  649. return(1);
  650.  
  651. } // end Game_Main
  652.  
  653.  
  654.