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

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