home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwdos / osdos.c < prev    next >
C/C++ Source or Header  |  1995-02-15  |  39KB  |  1,342 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     osdos.c
  4.  *
  5.  * Abstract : DOS specific implementation of OS specific files. Note:
  6.  *            the program entry point and top level control flow is
  7.  *            also performed here.
  8.  *
  9.  **********************************************************************
  10.  *
  11.  * This file is a product of Criterion Software Ltd.
  12.  *
  13.  * This file is provided as is with no warranties of any kind and is
  14.  * provided without any obligation on Criterion Software Ltd. or
  15.  * Canon Inc. to assist in its use or modification.
  16.  *
  17.  * Criterion Software Ltd. will not, under any
  18.  * circumstances, be liable for any lost revenue or other damages arising
  19.  * from the use of this file.
  20.  *
  21.  * Copyright (c) 1995 Criterion Software Ltd.
  22.  * All Rights Reserved.
  23.  *
  24.  * RenderWare is a trademark of Canon Inc.
  25.  *
  26.  ************************************************************************/
  27.  
  28. /*--- Include Files ---*/
  29.  
  30. #include "global.h"     /* Application global includes */
  31.  
  32. /* Dos specific include files */
  33. #include <i86.h>
  34. #include "rwdos.h"
  35. #include "doswrap.h"
  36.  
  37. /* Macro and Magic Number definitions */
  38.  
  39. #define KEY_RSHIFT      0x01
  40. #define KEY_LSHIFT      0x02
  41. #define KEY_CONTROL     0x04
  42. #define KEY_ALT         0x08
  43. #define KEY_SCRCLOCK    0x10
  44. #define KEY_NUMLOCK     0x20
  45. #define KEY_CAPLOCK     0x40
  46. #define KEY_INSERT      0x80
  47.  
  48. #define LORES_SCREEN_WIDTH  320
  49. #define LORES_SCREEN_HEIGHT 200
  50. #define LORES_CAMERA_WIDTH  LORES_SCREEN_WIDTH
  51. #define LORES_CAMERA_HEIGHT LORES_SCREEN_HEIGHT
  52.  
  53. #define HIRES_SCREEN_WIDTH  640
  54. #define HIRES_SCREEN_HEIGHT 480
  55. #define HIRES_CAMERA_WIDTH  PANEL_HOLE_WIDTH
  56. #define HIRES_CAMERA_HEIGHT PANEL_HOLE_HEIGHT
  57.  
  58.  
  59. #ifdef WITH_SCORE
  60.  
  61. #define SCORE_UP      CREAL(0.2)
  62. #define SCORE_RIGHT   CREAL(0.5)
  63. #define SCORE_FORWARD CREAL(2.5)
  64. #define SCORE_STARTX  CREAL(2.0)
  65. #define SCORE_STARTY  CREAL(1.4)
  66.  
  67.  
  68. /*--- Structure Definitions ---*/
  69.  
  70. /* AllSprites: A single global variable of this type is defined and used to hold
  71.  * global sprite data
  72.  */
  73.  
  74. typedef struct
  75. {
  76.     RwRect rClip;   /* The clip rectangle for the sprites */
  77.     int nDepth;     /* The current display depth. Used when masking sprites */
  78. } AllSprites;
  79.  
  80. AllSprites asGSprites;
  81.  
  82. /* Score definitions */
  83.  
  84. #define NUM_LEFT_IMAGES 4      /* The number of images used for the big rat */
  85.  
  86.  
  87. /* Score: A single global variable of this type is declared and used to hold
  88.  * all of the global score data
  89.  */
  90.  
  91. typedef struct
  92. {
  93.     RwClump *cpRat;         /* The clump for the small spinning rat */
  94.     RwMatrix4d *mpPos;      /* The absolute position matrix for the
  95.                                spinning rats */
  96.     RwMatrix4d *mpRot;      /* The incremental rotation that is applied to the
  97.                                rats each frame */
  98.     RwMatrix4d *mpOffset;   /* The matrix used to determine the 3D location
  99.                                that the score rats are drawn */
  100.     RwRaster   *spaLeftImages[NUM_LEFT_IMAGES]; /* The rasters for the big rat
  101.                                                    which changes dependant on
  102.                                                    the number of rats in the street */
  103.  
  104.     RwRaster *spTimesOne;           /* The raster for the x1 overlay */
  105.     RwRaster *spTimesFive;          /* The raster for the x5 overlay */
  106.     RwRaster *spTimesTwentyFive;    /* The raster for the x25 overlay */
  107. } Score;
  108.  
  109. Score sGScore;
  110.  
  111. /*--- Function Prototypes ---*/
  112.  
  113. static int AllSoundsAddSound(char *cpFilename, int nVolume, int nPeriod, int nChannel);
  114.  
  115. static int AllSpritesSetClip(RwInt32 nX, RwInt32 nY, RwInt32 nW, RwInt32 nH);
  116.  
  117. #endif /* WITH_SCORE */
  118.  
  119. /*--- Global Variables ---*/
  120.  
  121. static int nGLoRes;     /* TRUE if lores display else false */
  122. static int nGHiCol;     /* TRUE if hi color display else false */
  123.  
  124. #ifdef WITH_SCORE
  125. /************************************************************************
  126.  *
  127.  *      Function:       AllSpritesSetup()
  128.  *
  129.  *      Description:    Initialise the global sprite data
  130.  *
  131.  *      Parameters:     None
  132.  *
  133.  *      Return Value:   None
  134.  *
  135.  ************************************************************************/
  136. static int
  137. AllSpritesSetup(void)
  138. {
  139.   AllSpritesSetClip(0,0,0,0);
  140.   RwGetDeviceInfo(rwRENDERDEPTH,&asGSprites.nDepth,sizeof(asGSprites.nDepth));
  141.  
  142.   return TRUE;
  143. }
  144.  
  145. /************************************************************************
  146.  *
  147.  *      Function:       AllSpritesSetClip()
  148.  *
  149.  *      Description:    Set the clip rectangle for sprites
  150.  *
  151.  *      Parameters:     None
  152.  *
  153.  *      Return Value:   None
  154.  *
  155.  ************************************************************************/
  156. static int
  157. AllSpritesSetClip(RwInt32 nX, RwInt32 nY, RwInt32 nW, RwInt32 nH)
  158. {
  159.     asGSprites.rClip.x = nX;
  160.     asGSprites.rClip.y = nY;
  161.     asGSprites.rClip.w = nW;
  162.     asGSprites.rClip.h = nH;
  163.  
  164.     return TRUE;
  165. }
  166.  
  167. /************************************************************************
  168.  *
  169.  *      Function:       SpriteMask()
  170.  *
  171.  *      Description:    The supplied RwRaster is converted into a
  172.  *                      transparent one by overwriting all pixels of
  173.  *                      the specified color with the transparency value
  174.  *
  175.  *      Parameters:     rpSprite - the RwRaster to mask
  176.  *                      nX, nY - identifies the pixel in the RwRaster that
  177.  *                      contains the background color. All pixels in the
  178.  *                      raster that are this color will be made transparent
  179.  *
  180.  *      Return Value:   None
  181.  *
  182.  ************************************************************************/
  183. static void
  184. SpriteMask(RwRaster *rpSprite,int nX,int nY)
  185. {
  186.     short int *npData;
  187.     int nMask;
  188.     unsigned char *cpData;
  189.     unsigned char cMask;
  190.     int nW;
  191.     int nH;
  192.     int nStride;
  193.  
  194.     if (asGSprites.nDepth==8)
  195.     {
  196.         /* its an 8 bit raster */
  197.  
  198.         /* Get the background color */
  199.         cpData = (unsigned char *)RwGetRasterPixels(rpSprite);
  200.         cMask = cpData[(RwGetRasterStride(rpSprite)*nY)+nX];
  201.  
  202.         nStride = (RwGetRasterStride(rpSprite))-
  203.                    RwGetRasterWidth(rpSprite);
  204.  
  205.         /* And replace it with the transparent color */
  206.         for (nH = RwGetRasterHeight(rpSprite); nH>0;nH--)
  207.         {
  208.             for (nW = RwGetRasterWidth(rpSprite);nW>0;nW--)
  209.             {
  210.                 if ((*cpData)==cMask)
  211.                 {
  212.                     /* Its transparant really ! */
  213.                     (*cpData) = 0x0;
  214.                 }
  215.                 cpData++;
  216.             }
  217.             cpData+=nStride;
  218.         }
  219.     }
  220.     else
  221.     {
  222.         /* It's a 16 bit raster */
  223.  
  224.         /* Get the background color */
  225.         npData = (short int *)RwGetRasterPixels(rpSprite);
  226.         nMask = npData[((RwGetRasterStride(rpSprite)>>1)*nY)+nX];
  227.  
  228.         nStride = (RwGetRasterStride(rpSprite)>>1)-
  229.                   RwGetRasterWidth(rpSprite);
  230.  
  231.         /* And replace it with the transparent color */
  232.         for (nH = RwGetRasterHeight(rpSprite); nH>0;nH--)
  233.         {
  234.             for (nW = RwGetRasterWidth(rpSprite);nW>0;nW--)
  235.             {
  236.                 if ((*npData)==nMask)
  237.                 {
  238.                     /* Its transparant really ! */
  239.                     (*npData) = 0x0;
  240.                 }
  241.                 npData++;
  242.             }
  243.             npData+=nStride;
  244.         }
  245.     }
  246. }
  247.  
  248. /************************************************************************
  249.  *
  250.  *      Function:       SpriteWriteImage()
  251.  *
  252.  *      Description:
  253.  *
  254.  *      Parameters:     cpCamera - the RenderWare camera to write into
  255.  *                      rpSpr - the RwRaster to write
  256.  *                      nIX, nIY - relative position in outpu camera for
  257.  *                                 the centre of the sprite
  258.  *                      nX, nY - first sprite pixel to be drawn
  259.  *                      nW, nH - width and height of sprite area to be drawn
  260.  *
  261.  *      Return Value:   None
  262.  *
  263.  ************************************************************************/
  264. static void
  265. SpriteWriteImage(RwCamera *cpCamera, RwRaster *rpSpr,
  266.                  RwInt32 nIX, RwInt32 nIY,
  267.                  RwInt32 nX, RwInt32 nY, RwInt32 nW, RwInt32 nH)
  268. {
  269.     RwRaster *rpRas;
  270.     unsigned char *cpData;
  271.     unsigned char *cpSource;
  272.     unsigned short int *npData;
  273.     unsigned short *npSource;
  274.     int nCount;
  275.     int nSourceStride;
  276.     int nDataStride;
  277.  
  278.     /* Get the camera's image buffer */
  279.  
  280.     rpRas = (RwRaster *)RwGetCameraImage(cpCamera);
  281.  
  282.     if (asGSprites.nDepth==8)
  283.     {
  284.         /* 8 bit transfer */
  285.         cpSource = ((unsigned char *)RwGetRasterPixels(rpSpr)) +
  286.                     (RwGetRasterStride(rpSpr) * nY) + nX;
  287.  
  288.         cpData = ((unsigned char *)RwGetRasterPixels(rpRas)) +
  289.                   (RwGetRasterStride(rpRas) * nIY) + nIX;
  290.  
  291.         nSourceStride = RwGetRasterStride(rpSpr) - nW;
  292.         nDataStride = RwGetRasterStride(rpRas) - nW;
  293.  
  294.         for (;nH>0;nH--)
  295.         {
  296.             for (nCount=0; nCount < nW; nCount++)
  297.             {
  298.                 if (*cpSource++)
  299.                 {
  300.                     (*cpData)=(*cpSource);
  301.                 }
  302.                 cpData++;
  303.             }
  304.             cpSource+=nSourceStride;
  305.             cpData+=nDataStride;
  306.         }
  307.     }
  308.     else
  309.     {
  310.         /* 16 bit transfer */
  311.         npSource = (unsigned short int *)
  312.                    (((unsigned char *)RwGetRasterPixels(rpSpr)) +
  313.                    (RwGetRasterStride(rpSpr) * nY) + (nX<<1));
  314.  
  315.         npData =  (unsigned short int *)
  316.                   ((unsigned char *)RwGetRasterPixels(rpRas))+
  317.                   (nIY * RwGetRasterStride(rpRas))+ (nIX<<1);
  318.  
  319.         nSourceStride = (RwGetRasterStride(rpSpr)>>1) - nW;
  320.         nDataStride = (RwGetRasterStride(rpRas)>>1) - nW;
  321.  
  322.         for (;nH>0;nH--)
  323.         {
  324.             for (nCount=0; nCount < nW; nCount++)
  325.             {
  326.                 if (*npSource++)
  327.                 {
  328.                     (*npData)=(*npSource);
  329.                 }
  330.                 npData++;
  331.             }
  332.             npSource += nSourceStride;
  333.             npData += nDataStride;
  334.         }
  335.     }
  336. }
  337. #endif /* WITH_SCORE */
  338.  
  339. /************************************************************************
  340.  *
  341.  *      Function:       SpriteRender()
  342.  *
  343.  *      Description:    Render the sprite at the specified position in
  344.  *                      the image buffer of the supplied camera. The sprite
  345.  *                      will be clipped to the current global clip region.
  346.  *
  347.  *      Parameters:     cpCamera - the camera to write the sprite into
  348.  *                      rwSprite - the RwRaster to write.
  349.  *                      nIX, nIY - relative normalized offsets into the camera
  350.  *                                 image buffer
  351.  *
  352.  *      Return Value:   None
  353.  *
  354.  ************************************************************************/
  355. static void
  356. SpriteRender(RwCamera *cpCamera, RwRaster *rpSprite, RwInt32 nIX, RwInt32 nIY)
  357. {
  358.     RwInt32 nW, nH, nX, nY, nSW, nSH;
  359.  
  360.     if (!rpSprite)
  361.     {
  362.         return;
  363.     }
  364.  
  365.     nX = 0;
  366.     nY = 0;
  367.     nSW= nW = RwGetRasterWidth(rpSprite);
  368.     nSH= nH = RwGetRasterHeight(rpSprite);
  369.  
  370.     /* Clip the display region to the clip region */
  371.  
  372.     if ( (nIX > (asGSprites.rClip.x + asGSprites.rClip.w)) ||
  373.          ((nIX+nSW) < asGSprites.rClip.x) ||
  374.          (nIY > (asGSprites.rClip.y + asGSprites.rClip.h)) ||
  375.          ((nIY+nSH) < asGSprites.rClip.y) )
  376.     {
  377.         /* Its not on the screen */
  378.         return;
  379.     }
  380.  
  381.     /* Clip to the region size */
  382.  
  383.     if (nIX < asGSprites.rClip.x)
  384.     {
  385.         nX = asGSprites.rClip.x - nIX;
  386.         nW -= nX;
  387.     }
  388.     if ((nIX+nSW) > (asGSprites.rClip.x + asGSprites.rClip.w))
  389.     {
  390.         nW -= ((nIX+nSW) - (asGSprites.rClip.x + asGSprites.rClip.w));
  391.     }
  392.     if (nIY < asGSprites.rClip.y)
  393.     {
  394.         nY = asGSprites.rClip.y - nIY;
  395.         nH -= nY;
  396.     }
  397.     if ((nIY+nSH) > (asGSprites.rClip.y + asGSprites.rClip.h))
  398.     {
  399.         nH -= ((nIY+nSH) - (asGSprites.rClip.y+asGSprites.rClip.h));
  400.     }
  401.  
  402.     /* Check if after clipping all is ok */
  403.  
  404.     if ((nW <= 0) || (nH <= 0))
  405.     {
  406.         /* Nothing to display ! */
  407.         return;
  408.     }
  409.  
  410.     SpriteWriteImage(cpCamera, rpSprite, nIX+nX, nIY+nY, nX, nY, nW, nH);
  411. }
  412.  
  413. /************************************************************************
  414.  *
  415.  *      Function:       SpriteRenderRelative()
  416.  *
  417.  *      Description:    Draws a sprite at a relative normalized position.
  418.  *                      The position specified is where the CENTRE of the
  419.  *                      sprite will be located.
  420.  *
  421.  *      Parameters:     cpCam - the camera that the sprite will be rendered into
  422.  *                      rwSprite - the sprite to render
  423.  *                      nX, nY -  relative X and Y offsets into camera viewport
  424.  *                                these are normalised so spepcifying (0.5, 0.5)
  425.  *                                for example will draw the sprite in the centre
  426.  *                                of the cameras viewport
  427.  *
  428.  *      Return Value:   None
  429.  *
  430.  ************************************************************************/
  431. static void
  432. SpriteRenderRelative(RwCamera *cpCam, RwRaster *rpSprite, RwReal nX, RwReal nY)
  433. {
  434.     RwInt32 nW,nH,nCX,nCY;
  435.  
  436.     if (rpSprite)
  437.     {
  438.         RwGetCameraViewport(cpGCamera,&nCX,&nCY,&nW,&nH);
  439.  
  440.         nCX = REAL2INT(RMul(INT2REAL(nW),nX));
  441.         nCY = REAL2INT(RMul(INT2REAL(nH),nY));
  442.  
  443.         nCX -= RwGetRasterWidth(rpSprite) >> 1;
  444.         nCY -= RwGetRasterHeight(rpSprite) >> 1;
  445.  
  446.         SpriteRender(cpCam, rpSprite, nCX, nCY);
  447.     }
  448. }
  449.  
  450. /************************************************************************
  451.  *
  452.  *      Function:       OsBeginCameraUpdate()
  453.  *
  454.  *      Description:    Os specific version of RwBeginCameraUpdate().
  455.  *                      For MS Windows RwBeginCameraUpdate() is passed
  456.  *                      the handle to the window. We use the global
  457.  *                      handle that is setup in the main window handler.
  458.  *
  459.  *      Parameters:     Camera - the Camera to pass to RwBeginCameraUpdate()
  460.  *
  461.  *      Return Value:   None
  462.  *
  463.  ************************************************************************/
  464. void OsBeginCameraUpdate(RwCamera *Camera)
  465. {
  466.     RwBeginCameraUpdate(Camera, NULL);
  467. }
  468.  
  469. /************************************************************************
  470.  *
  471.  *      Function:       OsMaxScreenWidth()
  472.  *
  473.  *      Description:    The maximum screen width is an OS specific
  474.  *                      feature. This function returns this information to
  475.  *                      the main body of the application
  476.  *
  477.  *      Parameters:     None
  478.  *
  479.  *      Return Value:   TRUE if successful else FALSE
  480.  *
  481.  ************************************************************************/
  482. RwInt32 OsMaxScreenWidth(void)
  483. {
  484.     if (nGLoRes)
  485.     {
  486.         return ((RwInt32)LORES_SCREEN_WIDTH);
  487.     }
  488.     else
  489.     {
  490.         return ((RwInt32)HIRES_SCREEN_WIDTH);
  491.     }
  492. }
  493.  
  494. /************************************************************************
  495.  *
  496.  *      Function:       OsMaxScreenHeight()
  497.  *
  498.  *      Description:    The maximum screen height is an OS specific
  499.  *                      feature. This function returns this information to
  500.  *                      the main body of the application
  501.  *
  502.  *      Parameters:     None
  503.  *
  504.  *      Return Value:   TRUE if successful else FALSE
  505.  *
  506.  ************************************************************************/
  507. RwInt32 OsMaxScreenHeight(void)
  508. {
  509.     if (nGLoRes)
  510.     {
  511.         return ((RwInt32)LORES_SCREEN_HEIGHT);
  512.     }
  513.     else
  514.     {
  515.         return ((RwInt32)HIRES_SCREEN_HEIGHT);
  516.     }
  517. }
  518.  
  519. /************************************************************************
  520.  *
  521.  *      Function:       OsMaxCameraWidth()
  522.  *
  523.  *      Description:    The maximum camera width is an OS specific
  524.  *                      feature. This function returns this information to
  525.  *                      the main body of the application
  526.  *
  527.  *      Parameters:     None
  528.  *
  529.  *      Return Value:   TRUE if successful else FALSE
  530.  *
  531.  ************************************************************************/
  532. RwInt32 OsMaxCameraWidth(void)
  533. {
  534.     if (nGLoRes)
  535.     {
  536.         return ((RwInt32)LORES_CAMERA_WIDTH);
  537.     }
  538.     else
  539.     {
  540.         return ((RwInt32)HIRES_CAMERA_WIDTH);
  541.     }
  542. }
  543.  
  544. /************************************************************************
  545.  *
  546.  *      Function:       OsMaxCameraHeight()
  547.  *
  548.  *      Description:    The maximum camera height is an OS specific
  549.  *                      feature. This function returns this information to
  550.  *                      the main body of the application
  551.  *
  552.  *      Parameters:     None
  553.  *
  554.  *      Return Value:   TRUE if successful else FALSE
  555.  *
  556.  ************************************************************************/
  557. RwInt32 OsMaxCameraHeight(void)
  558. {
  559.     if (nGLoRes)
  560.     {
  561.         return ((RwInt32)LORES_CAMERA_HEIGHT);
  562.     }
  563.     else
  564.     {
  565.         return ((RwInt32)HIRES_CAMERA_HEIGHT);
  566.     }
  567. }
  568.  
  569. /************************************************************************
  570.  *
  571.  *      Function:       OsShowCameraImage()
  572.  *
  573.  *      Description:    Os specific version of RwShowCameraImage().
  574.  *                      For DOS the device specific parameter is NULL
  575.  *
  576.  *      Parameters:     None
  577.  *
  578.  *      Return Value:   None
  579.  *
  580.  ************************************************************************/
  581. void OsShowCameraImage()
  582. {
  583.     RwShowCameraImage(cpGCamera, NULL);
  584. }
  585.  
  586. /************************************************************************
  587.  *
  588.  *      Function:       OsError()
  589.  *
  590.  *      Description:    Os specific error handler. For DOS we just
  591.  *                      call printf
  592.  *
  593.  *      Parameters:     fmt - stdarg format string
  594.  *
  595.  *      Return Value:   None
  596.  *
  597.  ************************************************************************/
  598. void OsError(char *fmt, ...)
  599. {
  600.     va_list args;
  601.  
  602.     va_start(args, fmt);
  603.     vprintf (fmt, args);
  604.     va_end(args);
  605.     printf("\n");
  606. }
  607.  
  608. /************************************************************************
  609.  *
  610.  *      Function:       OsOpen()
  611.  *
  612.  *      Description:    Os specific RwOpen(). This function opens
  613.  *                      RenderWare and sets the Shape Path
  614.  *
  615.  *      Parameters:     None
  616.  *
  617.  *      Return Value:   TRUE if successful else FALSE
  618.  *
  619.  ************************************************************************/
  620. int OsOpen(void)
  621. {
  622.     long nError;
  623.     RwOpenArgument arg[4];
  624.  
  625.     if (nGHiCol)
  626.     {
  627.         arg[0].option = rwSCRDEPTH;
  628.         arg[0].value = (void *)16;
  629.     }
  630.     else
  631.     {
  632.         arg[0].option = rwSCRDEPTH;
  633.         arg[0].value = (void *)8;
  634.     }
  635.  
  636.      arg[1].option = rwSCRWIDTH;
  637.      arg[1].value = (void *)OsMaxScreenWidth();
  638.      arg[2].option = rwSCRHEIGHT;
  639.      arg[2].value = (void *)OsMaxScreenHeight();
  640.  
  641.     if (!RwOpenExt("DOSMOUSE", &nError, 3, &arg))
  642.     {
  643.         printf("Unable to access renderware!!\n");
  644.         switch (nError)
  645.         {
  646.         case E_RW_DOS_MODE_UNAVAILABLE:
  647.             printf("The installed VESA card is unable to switch to the resolution");
  648.             printf(" requested.\n");
  649.             printf("Either install a different video adapter or use a ");
  650.             printf("supported video mode.");
  651.             break;
  652.  
  653.         case E_RW_DOS_NO_VESA_BIOS:
  654.             printf("A VESA bios is unavailable on this machine.\n");
  655.             printf("Either use a VESA compatible Video Adapter or install a ");
  656.             printf("VESA bios emulation TSR.\n");
  657.             break;
  658.  
  659.         case E_RW_DOS_INCOMPATIBLE_BIOS:
  660.             printf("The VESA bios on this machine is not of high enough version ");
  661.             printf("to function\ncorrectly with RenderWare. Use a version 1.0 or");
  662.             printf(" higher VESA bios or TSR.\n");
  663.             break;
  664.  
  665.         case E_RW_DOS_NO_MOUSE:
  666.             printf("No Microsoft compatible mouse driver present.\n");
  667.             printf("Install a microsoft compatible mouse driver and try again.\n");
  668.             break;
  669.  
  670.         default:
  671.             printf("Unknown Error !!!!!!!!!!!!!!!\n");
  672.             break;
  673.  
  674.         }
  675.         return FALSE;
  676.     }
  677.     RwSetShapePath("SCRIPTS", rwPRECONCAT);
  678.     RwSetShapePath("TEXTURES", rwPRECONCAT);
  679.     RwSetShapePath(".", rwPRECONCAT);
  680.  
  681.     return TRUE;
  682. }
  683.  
  684. /************************************************************************
  685.  *
  686.  *      Function:       OsSetCameraViewport()
  687.  *
  688.  *      Description:    Os specific RwSetCameraViewport(). For DOS, the
  689.  *                      viewport size is dependant on the screen resolution
  690.  *                      so we have to take account of this before calling
  691.  *                      RwSetCameraViewport
  692.  *
  693.  *      Parameters:     None
  694.  *
  695.  *      Return Value:   None
  696.  *
  697.  ************************************************************************/
  698. void OsSetCameraViewport()
  699. {
  700.     if (nGLoRes)
  701.     {
  702.         RwSetCameraViewport(cpGCamera, 0,0,
  703.                             OsMaxCameraWidth(), OsMaxCameraHeight());
  704.     }
  705.     else
  706.     {
  707.         RwSetCameraViewport(cpGCamera, PANEL_HOLE_XOFFSET, PANEL_HOLE_YOFFSET,
  708.                             PANEL_HOLE_WIDTH, PANEL_HOLE_HEIGHT);
  709.     }
  710. }
  711.  
  712. /************************************************************************
  713.  *
  714.  *      Function:       OsInit()
  715.  *
  716.  *      Description:    Os specific application initialisation. This function
  717.  *                      is called once the palette has been set up and
  718.  *                      performs all of the device specific initialisation
  719.  *                      and object loading
  720.  *
  721.  *      Parameters:     None
  722.  *
  723.  *      Return Value:   TRUE if successful else FALSE
  724.  *
  725.  ************************************************************************/
  726. int OsInit()
  727. {
  728. #ifdef  WITH_SCORE
  729.     RwRect rViewport;
  730. #endif
  731.     RwRaster *rpTitle;
  732.     RwPointerImage piImage;
  733.     RwReal naWhite[3]={CREAL(1),CREAL(1),CREAL(1)};
  734.     RwReal naBlack[3]={CREAL(0),CREAL(0),CREAL(0)};
  735.  
  736.     /* Rematch the pointer image */
  737.  
  738.     piImage.image = NULL;
  739.     piImage.hotx=0;
  740.     piImage.hoty=0;
  741.     piImage.w = RwDeviceControl(rwSCRGETCOLOR,0,naBlack,sizeof(naBlack));
  742.     piImage.h = RwDeviceControl(rwSCRGETCOLOR,0,naWhite,sizeof(naWhite));
  743.  
  744.     RwDeviceControl(rwPOINTERSETIMAGE,0,&piImage,sizeof(piImage));
  745.  
  746.     /* Do the loading screen */
  747.  
  748.     if (!(rpTitle = RwReadRaster("title.bmp", 0)))
  749.     {
  750.         return FALSE;
  751.     }
  752.     RwSetCameraBackdrop(cpGCamera, rpTitle);
  753.     RwSetCameraBackdropOffset(cpGCamera, 0,0);
  754.  
  755.     RwSetCameraBackdropViewportRect(cpGCamera, 0,0,
  756.                                     RwGetRasterWidth(rpTitle),
  757.                                     RwGetRasterHeight(rpTitle));
  758.  
  759.     /* Put the title in the centre of the screen */
  760.  
  761.     RwSetCameraViewport(cpGCamera,
  762.                         (OsMaxScreenWidth() - RwGetRasterWidth(rpTitle))/2,
  763.                         (OsMaxScreenHeight() - RwGetRasterHeight(rpTitle))/2,
  764.                         RwGetRasterWidth(rpTitle), RwGetRasterHeight(rpTitle));
  765.  
  766.     OsBeginCameraUpdate(cpGCamera);
  767.     RwClearCameraViewport(cpGCamera);
  768.     RwEndCameraUpdate(cpGCamera);
  769.     OsShowCameraImage();
  770.  
  771.     RwDestroyRaster(rpTitle);
  772.  
  773.     OsSetCameraViewport();
  774.  
  775. #ifdef WITH_SCORE
  776.     /* Set up the sprites */
  777.  
  778.     if (!(AllSpritesSetup()))
  779.     {
  780.         return FALSE;
  781.     }
  782.  
  783.     /* Set up sprite structure */
  784.  
  785.     RwGetCameraViewport(cpGCamera,
  786.                 &rViewport.x,&rViewport.y,&rViewport.w,&rViewport.h);
  787.     AllSpritesSetClip(0,0,rViewport.w,rViewport.h);
  788. #endif
  789.  
  790.     rpGPanel = NULL;
  791.     if (!nGLoRes)
  792.     {
  793.         if (!(rpGPanel = RwReadRaster("panel", 0L)))
  794.         {
  795.             return FALSE;
  796.         }
  797.     }
  798.  
  799. #ifdef WITH_SCORE
  800.     if (!ScoreSetup())
  801.     {
  802.         return(FALSE);
  803.     }
  804. #endif
  805.  
  806.     return TRUE;
  807. }
  808.  
  809. /************************************************************************
  810.  *
  811.  *      Function:       OsTidy()
  812.  *
  813.  *      Description:    Clean up all of the stuff initialised in OsInit()
  814.  *
  815.  *      Parameters:     None
  816.  *
  817.  *      Return Value:   None
  818.  *
  819.  ************************************************************************/
  820. void OsTidy(void)
  821. {
  822. #ifdef WITH_SCORE
  823.     ScoreDestroy();
  824. #endif
  825.     if (!nGLoRes)
  826.     {
  827.         RwDestroyRaster(rpGPanel);
  828.     }
  829. }
  830.  
  831. #ifdef WITH_SCORE
  832. /************************************************************************
  833.  *
  834.  *      Function:       SpriteSetup()
  835.  *
  836.  *      Description:    Setup a single sprite
  837.  *
  838.  *      Parameters:     name - the name of the raster file to load
  839.  *                      x,y the offset into the raster to obtain the mask color
  840.  *
  841.  *      Return Value:   None
  842.  *
  843.  ************************************************************************/
  844. static RwRaster *SpriteSetup(char *name, int x, int y)
  845. {
  846.     RwRaster *raster = RwReadRaster(name, 0L);
  847.     if (raster)
  848.     {
  849.         SpriteMask(raster, x, y);
  850.     }
  851.     return(raster);
  852. }
  853.  
  854. /************************************************************************
  855.  *
  856.  *      Function:       ScoreSetup()
  857.  *
  858.  *      Description:    Initialise the score data structures
  859.  *
  860.  *      Parameters:     None
  861.  *
  862.  *      Return Value:   None
  863.  *
  864.  ************************************************************************/
  865. static int ScoreSetup(void)
  866. {
  867.     if (!(sGScore.cpRat = DoRwReadShape("ratsimpl.rwx")))
  868.     {
  869.         return FALSE;
  870.     }
  871.  
  872.     /* Load in the sprite images */
  873.  
  874.     if (!(sGScore.spaLeftImages[0]  = SpriteSetup("ratface4.bmp", 0, 0)) ||
  875.         !(sGScore.spaLeftImages[1]  = SpriteSetup("ratface3.bmp", 0, 0)) ||
  876.         !(sGScore.spaLeftImages[2]  = SpriteSetup("ratface2.bmp", 0, 0)) ||
  877.         !(sGScore.spaLeftImages[3]  = SpriteSetup("ratface1.bmp", 0, 0)))
  878.     {
  879.         return FALSE;
  880.     }
  881.  
  882.     if (!(sGScore.spTimesOne        = SpriteSetup("t1.bmp", 2, 2)) ||
  883.         !(sGScore.spTimesFive       = SpriteSetup("t5.bmp", 2, 2)) ||
  884.         !(sGScore.spTimesTwentyFive = SpriteSetup("t25.bmp", 2, 2)) )
  885.     {
  886.         return FALSE;
  887.     }
  888.  
  889.     /* Screen position */
  890.  
  891.     if (!(sGScore.mpPos = RwCreateMatrix()))
  892.     {
  893.         return FALSE;
  894.     }
  895.     RwIdentityMatrix(sGScore.mpPos);
  896.  
  897.     if (!(sGScore.mpRot = RwCreateMatrix()))
  898.     {
  899.         return FALSE;
  900.     }
  901.     RwIdentityMatrix(sGScore.mpRot);
  902.  
  903.     if (!(sGScore.mpOffset = RwCreateMatrix()))
  904.     {
  905.         return FALSE;
  906.     }
  907.     RwIdentityMatrix(sGScore.mpOffset);
  908.  
  909.     RwRotateMatrix(sGScore.mpRot,
  910.                    CREAL(0.01), CREAL(1), CREAL(0.1), CREAL(6), rwREPLACE);
  911.  
  912.     RwRotateMatrix(sGScore.mpOffset,
  913.                    CREAL(0.1), CREAL(-0.5), CREAL(2), CREAL(100), rwREPLACE);
  914.  
  915.     return TRUE;
  916. }
  917.  
  918. /************************************************************************
  919.  *
  920.  *      Function:       OsDisplayScore()
  921.  *
  922.  *      Description:    Overlay the score on top of the rendered image
  923.  *
  924.  *      Parameters:     dead - number of dead rats
  925.  *                      left - number of rats remaining
  926.  *
  927.  *      Return Value:   None
  928.  *
  929.  ************************************************************************/
  930. void OsDisplayScore(int dead, int left)
  931. {
  932.     int nCount;
  933.     int nRats;
  934.     int nAmo;
  935.     int nTmp;
  936.     RwV3d vPos;
  937.     RwV3d vAt;
  938.     RwV3d vUp;
  939.     RwV3d vRight;
  940.     RwV3d vTmp;
  941.     RwV3d vLeft;
  942.     RwReal naPos[4][4];
  943.     int nImage;
  944.  
  945.     RwMatrix4d *mpTmp;
  946.  
  947.     RwTransformMatrix(sGScore.mpPos, sGScore.mpRot, rwPOSTCONCAT);
  948.     RwOrthoNormalizeMatrix(sGScore.mpPos, sGScore.mpPos);
  949.  
  950.     mpTmp = RwScratchMatrix();
  951.     RwPushScratchMatrix();
  952.     RwIdentityMatrix(mpTmp);
  953.  
  954.     RwGetCameraPosition(cpGCamera,&vPos);
  955.  
  956.     RwGetCameraLookAt(cpGCamera, &vAt);
  957.     (*((RwV3d *)&naPos[2][0])) = vAt;
  958.  
  959.     RwScaleVector(&vAt, SCORE_FORWARD, &vAt);
  960.     RwAddVector(&vPos,&vAt,&vPos);
  961.  
  962.     RwGetCameraLookUp(cpGCamera, &vUp);
  963.     (*((RwV3d *)&naPos[1][0])) = vUp;
  964.  
  965.     RwScaleVector(&vUp, SCORE_STARTY, &vTmp);
  966.     RwAddVector(&vPos,&vTmp,&vPos);
  967.     RwScaleVector(&vUp, SCORE_UP, &vUp);
  968.  
  969.     vLeft = vPos;
  970.  
  971.     RwGetCameraLookRight(cpGCamera, &vRight);
  972.     (*((RwV3d *)&naPos[0][0])) = vRight;
  973.  
  974.     RwScaleVector(&vRight, SCORE_STARTX, &vTmp);
  975.     RwAddVector(&vPos,&vTmp,&vPos);
  976.     RwScaleVector(&vRight, SCORE_RIGHT, &vRight);
  977.  
  978.     /* vPos points to the start position */
  979.  
  980.     nRats = dead;
  981.     nCount = 0;
  982.  
  983.     (*((RwV3d *)&naPos[3][0])) = vPos;
  984.     RwSetMatrixElements(RwScratchMatrix(),naPos);
  985.  
  986.     while (nCount<3)
  987.     {
  988.         RwCopyMatrix(RwScratchMatrix(), mpTmp);
  989.  
  990.         RwTransformMatrix(mpTmp, sGScore.mpPos, rwPRECONCAT);
  991.  
  992.         nAmo = nRats%5;
  993.         nRats = nRats/5;
  994.  
  995.         for (nTmp=0; nTmp < nAmo; nTmp++)
  996.         {
  997.             /* Draw a rat */
  998.  
  999.             RwTransformClump(sGScore.cpRat, mpTmp, rwREPLACE);
  1000.             RwRenderClump(sGScore.cpRat);
  1001.             RwTranslateMatrix(mpTmp, -vUp.x, -vUp.y, -vUp.z,rwPOSTCONCAT);
  1002.             RwTransformMatrix(mpTmp, sGScore.mpOffset, rwPRECONCAT);
  1003.         }
  1004.  
  1005.         nCount++;
  1006.  
  1007.         /* Move one to the right */
  1008.  
  1009.         RwTranslateMatrix(RwScratchMatrix(),
  1010.                         -vRight.x,-vRight.y,-vRight.z,rwPOSTCONCAT);
  1011.     }
  1012.     RwPopScratchMatrix();
  1013.  
  1014.     /* Display the amount left */
  1015.  
  1016.     nImage = (left * (NUM_LEFT_IMAGES-1))/RAT_MAXIMUM;
  1017.  
  1018.     SpriteRenderRelative(cpGCamera,sGScore.spaLeftImages[nImage],CREAL(0.08),CREAL(0.08));
  1019.  
  1020.     SpriteRenderRelative(cpGCamera,sGScore.spTimesOne,CREAL(0.9),CREAL(0.052));
  1021.     SpriteRenderRelative(cpGCamera,sGScore.spTimesFive,CREAL(0.8),CREAL(0.052));
  1022.     SpriteRenderRelative(cpGCamera,sGScore.spTimesTwentyFive,CREAL(0.7),CREAL(0.052));
  1023. }
  1024.  
  1025. /************************************************************************
  1026.  *
  1027.  *      Function:       ScoreDestroy()
  1028.  *
  1029.  *      Description:    Destroy the score data structures
  1030.  *
  1031.  *      Parameters:     None
  1032.  *
  1033.  *      Return Value:   None
  1034.  *
  1035.  ************************************************************************/
  1036. static void ScoreDestroy(void)
  1037. {
  1038.     RwDestroyClump(sGScore.cpRat);
  1039.  
  1040.     RwDestroyMatrix(sGScore.mpPos);
  1041.     RwDestroyMatrix(sGScore.mpRot);
  1042.     RwDestroyMatrix(sGScore.mpOffset);
  1043.  
  1044.     RwDestroyRaster(sGScore.spaLeftImages[0]);
  1045.     RwDestroyRaster(sGScore.spaLeftImages[1]);
  1046.     RwDestroyRaster(sGScore.spaLeftImages[2]);
  1047.     RwDestroyRaster(sGScore.spaLeftImages[3]);
  1048.  
  1049.     RwDestroyRaster(sGScore.spTimesOne);
  1050.     RwDestroyRaster(sGScore.spTimesFive);
  1051.     RwDestroyRaster(sGScore.spTimesTwentyFive);
  1052. }
  1053. #endif
  1054. /************************************************************************
  1055.  *
  1056.  *      Function:       DosGetKey()
  1057.  *
  1058.  *      Description:    Get the ascii key code of any depressed key.
  1059.  *
  1060.  *      Parameters:     None
  1061.  *
  1062.  *      Return Value:   0 if no key pressed else ASCII value for key pressed
  1063.  *
  1064.  ************************************************************************/
  1065. static int DosGetKey(void)
  1066. {
  1067.     union REGPACK rp;
  1068.  
  1069.     memset(&rp,0,sizeof(rp));
  1070.     rp.h.ah = 0x06;
  1071.     rp.h.dl = 0xff;
  1072.  
  1073.     intr(0x21,&rp);
  1074.  
  1075.     if (!(rp.w.flags & 0x40 )) {       /* Check Z flag */
  1076.         /* Got key */
  1077.  
  1078.         if (rp.h.al) {
  1079.             return ((int)rp.h.al);
  1080.         };
  1081.  
  1082.         memset(&rp,0,sizeof(rp));
  1083.         rp.h.ah = 0x06;
  1084.         rp.h.dl = 0xff;
  1085.         intr(0x21,&rp);
  1086.  
  1087.         if (!(rp.w.flags & 0x40)) {
  1088.             return ((int)rp.h.al);
  1089.         };
  1090.  
  1091.         return (rp.h.al|0x80);
  1092.     };
  1093.  
  1094.     return 0;
  1095. }
  1096.  
  1097. /************************************************************************
  1098.  *
  1099.  *      Function:       DosShiftCtrl()
  1100.  *
  1101.  *      Description:    Get the status of the Shift Control keys.
  1102.  *
  1103.  *      Parameters:     None
  1104.  *
  1105.  *      Return Value:   Bit field indicating the key status
  1106.  *                      Bit         Meaning
  1107.  *                       0          Right Shift
  1108.  *                       1          Left Shift
  1109.  *                       2          Ctrl
  1110.  *                       3          Alt
  1111.  *                       4          Scroll Lock
  1112.  *                       5          Num Lock
  1113.  *                       6          Caps Lock
  1114.  *                       7          Insert on
  1115.  *
  1116.  ************************************************************************/
  1117. static int
  1118. DosShiftCtrl(void)
  1119. {
  1120.     union REGPACK rp;
  1121.  
  1122.     memset(&rp,0,sizeof(rp));
  1123.  
  1124.     rp.h.ah=0x02;
  1125.     intr(0x16,&rp);
  1126.  
  1127.     return ((int)rp.h.al);
  1128. }
  1129.  
  1130. /************************************************************************
  1131.  *
  1132.  *      Function:       ReadFromCommandLine()
  1133.  *
  1134.  *      Description:    Parse the arguments passed to the program. For this
  1135.  *                      program the valid arguments are -hires for a high
  1136.  *                      resolution display and -hicol for 16 bit color
  1137.  *
  1138.  *      Parameters:     argc, argv - standard C program arguments
  1139.  *
  1140.  *      Return Value:   None
  1141.  *
  1142.  ************************************************************************/
  1143. static void ReadFromCommandLine(int argc, char *argv[])
  1144. {
  1145.     int i;
  1146.  
  1147.     nGLoRes = 1;
  1148.     nGHiCol = 0;
  1149.     for (i=1; i<argc; i++)
  1150.     {
  1151.         if (!strcmp(argv[i],"-hires"))
  1152.             nGLoRes = 0;
  1153.         if (!strcmp(argv[i],"-hicol"))
  1154.             nGHiCol = 1;
  1155.     }
  1156. }
  1157.  
  1158.  
  1159. /************************************************************************
  1160.  *
  1161.  *      Function:       main()
  1162.  *
  1163.  *      Description:    Main entry point, All of the top level control
  1164.  *                      flow is handle directly here.
  1165.  *
  1166.  *      Parameters:     argc, argv - standard C parameters
  1167.  *
  1168.  *      Return Value:   None
  1169.  *
  1170.  ************************************************************************/
  1171. void
  1172. main(int nArgc,char *saArgv[])
  1173. {
  1174.     int nMouseX,nMouseY;
  1175.     int nKey;
  1176.     int nMouseBut, nOldMouseBut, nOldMouseX, nOldMouseY;
  1177.     int nDX,nDY;
  1178.     int nChange;
  1179.     int nCtrlShift;
  1180.     RwErrorCode eCode;
  1181.  
  1182.     /* Initialise the Random Number Seed */
  1183.  
  1184.     RwSRandom(time(0));
  1185.  
  1186.     ReadFromCommandLine(nArgc, saArgv);
  1187.  
  1188.     if (!Init3D())
  1189.     {
  1190.         eCode = RwGetError();
  1191.  
  1192.         switch(eCode)
  1193.         {
  1194.         case E_RW_BADOPEN:
  1195.             OsError("E_RW_BADOPEN");
  1196.             break;
  1197.  
  1198.         case E_RW_INTERNAL:
  1199.             OsError("E_RW_INTERNAL: Contact RenderWare Support");
  1200.             break;
  1201.         }
  1202.         exit(-1);
  1203.     }
  1204.  
  1205.   /* Load all of the sound effects */
  1206.  
  1207. #ifdef WITH_SOUND
  1208.     AllSoundsAddSound("gun.sb",0x1f,150,0);
  1209.     AllSoundsAddSound("ricochet.sb",0x2f,200,1);
  1210.     AllSoundsAddSound("squish.sb",0x3f,400,2);
  1211.     AllSoundsAddSound("squeak.sb",0x3f,200,2);
  1212.     AllSoundsAddSound("ratty.sb",0x3f,50,2);
  1213.     AllSoundsAddSound("boink.sb",0x3f,300,3);
  1214.     AllSoundsAddSound("ratty2.sb",0x3f,50,2);
  1215.     AllSoundsAddSound("clang.sb",0x3f,400,2);
  1216. #endif
  1217.  
  1218.     /* paint display for the first time */
  1219.     if (!nGLoRes)
  1220.     {
  1221.         HandlePaint();
  1222.     }
  1223.  
  1224.     RwDPointerDisplay(&nOldMouseX,&nOldMouseY,&nOldMouseBut);
  1225.  
  1226.     nKey = DosGetKey();
  1227.  
  1228.     while (nKey!=27)
  1229.     {
  1230.         /* ESC quits */
  1231.  
  1232.         RwDPointerDisplay(&nMouseX,&nMouseY,&nMouseBut);
  1233.  
  1234.         nKey = DosGetKey();
  1235.  
  1236.         if ((nKey == 'g')||(nKey=='G'))
  1237.         {
  1238.             GunToggle();
  1239.         }
  1240.  
  1241.         if ((nKey == 'f')||(nKey=='F'))
  1242.         {
  1243.             ToggleFlyCamera();
  1244.         }
  1245.  
  1246.         nCtrlShift = DosShiftCtrl();
  1247.  
  1248.         nDX =(nMouseX-nOldMouseX);
  1249.         nDY =(nMouseY-nOldMouseY);
  1250.  
  1251.         nChange = (nMouseBut&(2+8)) | ( (nOldMouseBut&(2+8)) >>1 );
  1252.  
  1253.         switch (nChange)
  1254.         {
  1255.             case 0+0:
  1256.             case 2+1:
  1257.             case 8+4:
  1258.             case 8+2+4+1:
  1259.         break;
  1260.  
  1261.             case 2:
  1262.             case 8+2+4:
  1263.                 /* Left Button Down */
  1264.                 HandleLeftButtonDown(nMouseX, nMouseY,
  1265.                                     nCtrlShift & KEY_CONTROL,
  1266.                                     nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1267.         break;
  1268.  
  1269.             case 8:
  1270.             case 8+2+1:
  1271.                 /* Right Button Down */
  1272.                 HandleRightButtonDown(nMouseX, nMouseY,
  1273.                                     nCtrlShift & KEY_CONTROL,
  1274.                                     nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1275.             break;
  1276.  
  1277.             case 8+1:
  1278.                 /* Right down left Up */
  1279.                 HandleLeftButtonUp();
  1280.                 HandleRightButtonDown(nMouseX, nMouseY,
  1281.                                       nCtrlShift & KEY_CONTROL,
  1282.                                       nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1283.                 break;
  1284.  
  1285.             case 2+4:
  1286.                 /* Right up left Down */
  1287.                 HandleRightButtonUp();
  1288.                 HandleLeftButtonDown(nMouseX, nMouseY,
  1289.                                       nCtrlShift & KEY_CONTROL,
  1290.                                       nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1291.                 break;
  1292.  
  1293.             case 8+2:
  1294.                 /* Left down RIght Down */
  1295.                 HandleRightButtonDown(nMouseX, nMouseY,
  1296.                                       nCtrlShift & KEY_CONTROL,
  1297.                                       nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1298.                 HandleLeftButtonDown(nMouseX, nMouseY,
  1299.                                       nCtrlShift & KEY_CONTROL,
  1300.                                       nCtrlShift & (KEY_RSHIFT|KEY_LSHIFT));
  1301.                 break;
  1302.  
  1303.             case 1+4:
  1304.                 /* Left up Right Up */
  1305.                 HandleRightButtonUp();
  1306.                 HandleLeftButtonUp();
  1307.                 break;
  1308.  
  1309.             case 1:
  1310.             case 8+4+1:
  1311.                 /* Left up */
  1312.                 HandleLeftButtonUp();
  1313.                 break;
  1314.  
  1315.             case 4:
  1316.             case 2+4+1:
  1317.                 /* Right up */
  1318.                 HandleRightButtonUp();
  1319.                 break;
  1320.         }
  1321.         if (nDX||nDY)
  1322.         {
  1323.             /* Mouse Move  */
  1324.             HandleMouseMove(nMouseX,nMouseY);
  1325.         }
  1326.  
  1327.         HandleTimer();
  1328.  
  1329.         nOldMouseX = nMouseX;
  1330.         nOldMouseY = nMouseY;
  1331.         nOldMouseBut = nMouseBut;
  1332.     }
  1333.  
  1334.     /*
  1335.      * Tidy up the 3D (RenderWare) components of the application.
  1336.      */
  1337.  
  1338.     TidyUp3D();
  1339.  
  1340.     exit(0);
  1341. }
  1342.