home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / apilot.lha / APilot / APilot_Ser / main_old.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-03  |  25.3 KB  |  858 lines

  1. /**************************************************************************
  2.  *
  3.  * main.c -- APilot, an xpilot like game for the Amiga.
  4.  *
  5.  *-------------------------------------------------------------------------
  6.  * Authors: Casper Gripenberg  (casper@alpha.hut.fi)
  7.  *          Kjetil Jacobsen  (kjetilja@stud.cs.uit.no)
  8.  *
  9.  */
  10.  
  11. /*------------------------------------------------------------------------*/
  12.  
  13. #include <math.h> 
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <string.h>
  18. #include <exec/types.h>             /* The Amiga data types file.         */
  19. #include <exec/memory.h>
  20. #include <devices/input.h>
  21. #include <devices/timer.h>
  22. #include <intuition/intuition.h>    /* Intuition data strucutres, etc.    */
  23. #include <graphics/displayinfo.h>   /* Release 2 Amiga display mode ID's  */
  24. #include <libraries/dos.h>          /* Official return codes defined here */
  25.  
  26. #include <proto/exec.h>
  27. #include <proto/input.h>
  28. #include <proto/intuition.h>
  29. #include <proto/graphics.h>
  30. #include <proto/diskfont.h>
  31. #include <proto/timer.h>
  32. #include <proto/dos.h>
  33.  
  34. #include <libraries/asl.h>
  35. #include <proto/asl.h>
  36.  
  37. /*------------------------------------------------------------------------*/
  38.  
  39. #include "map_protos.h"
  40. #include "points_protos.h"
  41. #include "ships_protos.h"
  42. #include "lists_protos.h"
  43. #include "cannon_protos.h"
  44. #include "collision_protos.h"
  45. #include "fuelpod_protos.h"
  46. #include "misc_protos.h"
  47. #include "vertb_protos.h"
  48. #include "prefs_protos.h"
  49. #include "serial_protos.h"
  50. #include "main_protos.h"
  51.  
  52.  
  53. #include "common.h"
  54. #include "vertb.h"
  55. #include "map.h"
  56. #include "prefs.h"
  57.  
  58. /*------------------------------------------------------------------------*/
  59.  
  60. /* Disable ctrl-c handling */
  61. void __regargs __chkabort(void);
  62. void __regargs __chkabort(void) { return; }
  63.  
  64. /*------------------------------------------------------------------------*/
  65. char *version = "$VER: APilot is still beta (22.03.94)";
  66.  
  67. /*------------------------------------------------------------------------*/
  68.  
  69. /*
  70.  * This is where all the action is
  71.  */
  72. AWorld World;
  73.  
  74. /*
  75.  * For rawkey interpreting.
  76.  */
  77. #define RAWKEY_KP_MINUS 74
  78. #define RAWKEY_KP_PLUS  94
  79. #define RAWKEY_KP_STAR  93
  80. #define RAWKEY_F        35
  81. #define RAWKEY_T        20
  82. #define RAWKEY_Q        16
  83. #define RAWKEY_A        32
  84. #define RAWKEY_S        33
  85. #define RAWKEY_ENTER    68
  86. #define RAWKEY_SPACE    64
  87.  
  88. /* This one is for the screenmode, sizes, etc. */
  89. UserPrefs prefs;
  90.  
  91. #ifdef CPU_USAGE
  92. static BOOL   cpu_meter   = FALSE;
  93. struct Library *TimerBase = NULL;
  94. static struct timerequest tr;
  95. #endif
  96.  
  97. /*
  98.  * Global structures and variables needed in this file
  99.  */
  100. static BYTE   deviceopen  = 1;
  101. static UWORD  w_framerate = APILOT_NFR;  /* Wanted framerate */
  102. static UWORD  oldrptdelay;
  103. static struct TextFont    *hudFont  = 0;
  104. static struct Screen      *myScreen = NULL;
  105. static struct Window      *myWindow = NULL;
  106. static struct BitMap      *myBitMap[MY_BUFFERS];
  107. static struct RastPort    myRP[MY_BUFFERS];
  108. static struct DBufInfo    *myDBI     = NULL;
  109. static struct MsgPort     *inputPort = NULL;
  110. static struct MsgPort     *dbufport  = NULL;
  111. static struct timerequest *inputReqBlk = NULL;
  112.  
  113. /*------------------------------------------------------------------------*/
  114.  
  115. /*
  116.  * init_world -- Initializes all data in the World structure.
  117.  *
  118.  */
  119. void
  120. init_world( void )
  121. {
  122.   APTR *dummy;
  123.  
  124.   World.Height = 0;
  125.   World.Width  = 0;
  126.  
  127.   World.gravity = DEF_GRAVITY * PRECS;
  128.  
  129.   if ( (World.players = (AShip *) malloc(sizeof(AShip))) == NULL )
  130.     cleanExit( RETURN_WARN, "** Unable to get memory for players.\n" );
  131.   if ( (dummy =  malloc(sizeof(AShip))) == NULL )
  132.     cleanExit( RETURN_WARN, "** Unable to get memory for players.\n" );
  133.   ((AShip *)dummy)->next = (AShip *)dummy;
  134.   World.players->next = (AShip *)dummy;
  135.  
  136.   if ( (World.fuelpods = (AFuelPod *) malloc(sizeof(AFuelPod))) == NULL )
  137.     cleanExit( RETURN_WARN, "** Unable to get memory for fuelpods.\n" );
  138.   if ( (dummy =  malloc(sizeof(AFuelPod))) == NULL )
  139.     cleanExit( RETURN_WARN, "** Unable to get memory for fuelpods.\n" );
  140.   ((AFuelPod *)dummy)->next = (AFuelPod *)dummy;
  141.   World.fuelpods->next = (AFuelPod *)dummy;
  142.  
  143.   if ( (World.cannons = (ACannon *) malloc(sizeof(ACannon))) == NULL )
  144.     cleanExit( RETURN_WARN, "** Unable to get memory for cannons.\n" );
  145.   if ( (dummy = malloc(sizeof(ACannon))) == NULL )
  146.     cleanExit( RETURN_WARN, "** Unable to get memory for cannons.\n" );
  147.   ((ACannon *)dummy)->next = (ACannon *)dummy;
  148.   World.cannons->next = (ACannon *)dummy;
  149.  
  150.   if ( (World.bases = (ABase *) malloc(sizeof(ABase))) == NULL )
  151.     cleanExit( RETURN_WARN, "** Unable to get memory for bases.\n" );
  152.   if ( (dummy = malloc(sizeof(ABase))) == NULL )
  153.     cleanExit( RETURN_WARN, "** Unable to get memory for bases.\n" );
  154.   ((ABase *)dummy)->next = (ABase *)dummy;
  155.   World.bases->next = (ABase *)dummy;
  156.  
  157.   if ( (World.players = (AShip *) malloc(sizeof(AShip))) == NULL )
  158.     cleanExit( RETURN_WARN, "** Unable to get memory for players.\n" );
  159.   if ( (dummy = malloc(sizeof(AShip))) == NULL )
  160.     cleanExit( RETURN_WARN, "** Unable to get memory for players.\n" );
  161.   ((AShip *)dummy)->next = (AShip *)dummy;
  162.   World.players->next = (AShip *)dummy;
  163.   
  164.   World.points  = NULL;
  165.  
  166.   /* Local stuff */
  167.   World.framerate = APILOT_NFR;
  168.   World.hudon     = TRUE;
  169.   World.shld_bm   = NULL;
  170. }
  171.  
  172. /*------------------------------------------------------------------------*/
  173.  
  174. /*
  175.  * init_display -- Opens a screen with a backdrop window.
  176.  *             
  177.  */
  178. void
  179. init_display( void )
  180. {
  181.   int    h, i, j;
  182.   int    myScreenLEdge;
  183.   struct Screen wbScreen;
  184.   struct RastPort rp;
  185.   UWORD  pens[] = { (UWORD)~0 };
  186.   
  187. #ifdef DYN_SCR
  188.   struct ScreenModeRequester *req;
  189.   char *Postext = "Play";
  190.   char *Toptext = "Select APilot ScreenMode";
  191. #endif
  192.   
  193.   /* The first white will be faded to black later for a nice effect :) */
  194.   struct ColorSpec mycolors[] = { { 0, 15, 15, 15 },        /* White */
  195.                                   { 1, 13,  4,  4 },        /* Red   */
  196.                                   { 2,  5,  5, 14 },        /* Blue  */
  197.                                   { 3, 13, 13, 13 },        /* White */
  198.                                   {-1,  0,  0,  0 } };
  199.  
  200.   /***************************************************************
  201.    * SAS Handles auto-opening and closing of all needed librarys *
  202.    ***************************************************************/ 
  203.  
  204. #ifdef DYN_SCR
  205.  
  206.   if (!prefs.native_mode) {
  207.     /* Allocate requester, seems like  the player want another screenmode  */
  208.     if ((req = AllocAslRequestTags(ASL_ScreenModeRequest,
  209.                    ASLSM_DoOverscanType,1,
  210.                    ASLSM_MinWidth,MINResX,
  211.                    ASLSM_MaxWidth,MAXResX,
  212.                    ASLSM_MinHeight,MINResY,
  213.                    ASLSM_MaxHeight,MAXResY,
  214.                    ASLSM_TitleText,Toptext,
  215.                    ASLSM_PositiveText,Postext,
  216.                    TAG_DONE)) == NULL)
  217.       cleanExit( RETURN_WARN, "** Unable to allocate screenmode-requester.\n" );
  218.     
  219.     /* Prompt user */
  220.     if (!AslRequestTags(req,
  221.             ASLSM_DoOverscanType,1,
  222.             ASLSM_MinWidth,MINResX,
  223.             ASLSM_MaxWidth,MAXResX,
  224.             ASLSM_MinHeight,MINResY,
  225.             ASLSM_MaxHeight,MAXResY,
  226.             ASLSM_TitleText,Toptext,
  227.             ASLSM_PositiveText,Postext,
  228.             TAG_DONE))
  229.       cleanExit( RETURN_WARN, "** Unable to get screenmode.\n" ); 
  230.     
  231.     /* Requester turned out successfully, store values */
  232.     prefs.dpy_oscan = req->sm_OverscanType;
  233.     prefs.dpy_width = (int) (req->sm_DisplayWidth-1) | 1;  /* Ensure odd values */
  234.     prefs.dpy_height = (int) (req->sm_DisplayHeight-1) | 1;
  235.     prefs.dpy_modeid = req->sm_DisplayID;
  236.   
  237.     /* Now free requester memory */
  238.     FreeAslRequest(req);
  239.   }
  240.  
  241. #endif
  242.   
  243.   /* Allocate all bitmaps needed for display buffering. */
  244.   for( i = 0; i < MY_BUFFERS; i++ ) {
  245.     myBitMap[i] = AllocBitMap( SCR_WIDTH  + MAP_BLOCKSIZE*2,
  246.                   SCR_HEIGHT + MAP_BLOCKSIZE*2,
  247.                   SCR_DEPTH, 
  248.                   BMF_CLEAR|BMF_DISPLAYABLE, NULL );
  249.     
  250.     if( myBitMap[i] == NULL )
  251.       cleanExit( RETURN_WARN, "** Unable to allocate bitmaps.\n" );
  252.     
  253.     /* Init the rastport and attach the corresponding bitmap */
  254.     InitRastPort( &myRP[i] );
  255.     myRP[i].BitMap = myBitMap[i];
  256.   }
  257.   
  258.   /*
  259.    * Make a temporatry bitmap which we will use to draw the
  260.    * ship shield images into. The bitmap will then later be used for 
  261.    * blitting the shield images to display memory.
  262.    */
  263.   World.shld_bm = AllocBitMap( (SHL_SIZE*2+1)*SHL_ANIM, 
  264.                                SHL_SIZE*2+1,
  265.                                SCR_DEPTH, 
  266.                                BMF_CLEAR|BMF_DISPLAYABLE, 
  267.                                myBitMap[0] );
  268.   if ( World.shld_bm == NULL )
  269.     cleanExit( RETURN_WARN, "** Unable to allocate bitmaps.\n" );
  270.   
  271.   InitRastPort( &rp );
  272.   rp.BitMap = World.shld_bm;
  273.   
  274.   /* Draw some shield images for animation. */
  275.   for (i = 0; i < SHL_ANIM; i++)
  276.     DrawEllipse(&rp, SHL_SIZE+((SHL_SIZE*2+1)*i), SHL_SIZE, SHL_SIZE, SHL_SIZE);
  277.  
  278.   /*
  279.    * Draw some 'holes' into the circles so they look nicer. Last image is
  280.    * kept from being changed, as it is used for clearing.
  281.    */
  282.   SetAPen(&rp, 0);
  283.  
  284.   for (h = 0; h < SHL_ANIM-1; h++)
  285.     for (i = 0, j = h; i < 360; i++,j++) { 
  286.       if (j > 15)
  287.         WritePixel(&rp, (long)(SHL_SIZE+0.5 + 
  288.                                SHL_SIZE * sin((double)PI/180*i)) + ((SHL_SIZE*2+1)*h),
  289.                         (long)(SHL_SIZE+0.5 + 
  290.                                SHL_SIZE * cos((double)PI/180*i)));
  291.       if (j >= 20) j = 0;
  292.     }
  293.  
  294.   /*
  295.    * Get info about the wb screen so we can nicely center our own
  296.    * screen in the 'middle' of the wbscreen. We don't need this for
  297.    * dynamic screens, as they use standard clip-regions.
  298.    *
  299.    * Yes we do :) Think about an apilot screen smaller than the
  300.    * wbscreen for example. Could happen if the user does NOT
  301.    * choose the screenmode-requester option in the command line.
  302.    * A smaller screen would be positioned at the left border
  303.    * of the standard clip-region..Looks ugly :(
  304.    */
  305.   GetScreenData(&wbScreen, sizeof(struct Screen), WBENCHSCREEN, NULL);
  306.   myScreenLEdge = (wbScreen.Width-SCR_WIDTH)/2 + wbScreen.LeftEdge;
  307.   if (myScreenLEdge < 0) myScreenLEdge = 0;
  308.   
  309.   /* Open the screen */
  310.   myScreen = OpenScreenTags(NULL,
  311.                             SA_Left,      myScreenLEdge,
  312.                             SA_Width,     SCR_WIDTH,
  313.                             SA_Height,    SCR_HEIGHT, 
  314.                             SA_BitMap,    myBitMap[0],
  315.                             SA_Pens,      (ULONG)pens, 
  316.                             SA_Colors,    mycolors,
  317.                             SA_DisplayID, prefs.dpy_modeid,
  318.                             SA_AutoScroll,0,
  319.                             SA_Overscan,  prefs.dpy_oscan,
  320.                             SA_Quiet,     1,
  321.                             SA_Type,      CUSTOMSCREEN | CUSTOMBITMAP,
  322.                             SA_Depth,     SCR_DEPTH,
  323.                             SA_Title,     (ULONG)"APilot",
  324.                             TAG_DONE);
  325.   
  326.   if (myScreen != NULL) {
  327.  
  328.     /* 
  329.      * Now set the bitmap offsets so that part of the bitmap is outside
  330.      * the visible screen. This way we don't have to do line clipping
  331.      * on map-blocks and ships.
  332.      */
  333.     myScreen->ViewPort.RasInfo->RxOffset = MAP_BLOCKSIZE; 
  334.     myScreen->ViewPort.RasInfo->RyOffset = MAP_BLOCKSIZE;
  335.     ScrollVPort(&myScreen->ViewPort);
  336.  
  337.     /* Make the screen titlebar go behind the Backdrop window */
  338.     ShowTitle(myScreen, FALSE);
  339.  
  340.     /* ... and open the window */
  341.     myWindow = OpenWindowTags(NULL,
  342.                               /* Specify window dimensions and limits */
  343.                               WA_Left,         0,
  344.                               WA_Top,          0,
  345.                               WA_Width,        SCR_WIDTH,
  346.                               WA_Height,       SCR_HEIGHT,
  347.                               WA_MaxWidth,     ~0,
  348.                               WA_MaxHeight,    ~0,
  349.                               /* Specify the system gadgets we want */
  350.                               WA_CloseGadget,  FALSE,
  351.                               WA_SizeGadget,   FALSE,
  352.                               WA_DepthGadget,  FALSE,
  353.                               WA_DragBar,      FALSE,
  354.                               WA_Borderless,   TRUE,
  355.                               /* Specify other attributes           */
  356.                               WA_RMBTrap,      TRUE,
  357.                               WA_RptQueue,     0,
  358.                               WA_Backdrop,     FALSE,
  359.                               WA_Activate,     TRUE,
  360.                               WA_NoCareRefresh,TRUE,
  361.                               /* Specify the events we want to know about */
  362.                               WA_IDCMP,        IDCMP_RAWKEY |
  363.                                                IDCMP_INACTIVEWINDOW |
  364.                                                IDCMP_ACTIVEWINDOW,
  365.                               /* Attach the window to the open screen ...*/
  366.                               WA_CustomScreen, myScreen,
  367.                               WA_Title,        NULL,
  368.                               WA_ScreenTitle,  NULL,
  369.                               TAG_DONE);
  370.     if (myWindow != NULL) {
  371.       do_fade();
  372.       return;
  373.     }
  374.   }
  375.   cleanExit( RETURN_WARN, "** Unable to initialize screen\n" );  
  376. }
  377.  
  378. /*------------------------------------------------------------------------*/
  379.  
  380. /*
  381.  * init_font -- Opens a font from disk for the HUD display.
  382.  *
  383.  */
  384. void
  385. init_font(void)
  386. {
  387.   int i;
  388.   struct TextAttr  hudtextAttr;
  389.  
  390.   hudtextAttr.ta_Name  = "SystemThin.font";
  391.   hudtextAttr.ta_YSize = 8;
  392.   hudtextAttr.ta_Style = FS_NORMAL;
  393.   hudtextAttr.ta_Flags = FPF_DISKFONT | FPF_DESIGNED;
  394.  
  395.   if ((hudFont = OpenDiskFont(&hudtextAttr)) == 0)
  396.     cleanExit( RETURN_WARN, "** Unable to open font 'SystemThin'." );
  397.   
  398.   for (i = 0; i < MY_BUFFERS; i++) {
  399.     SetFont(&myRP[i], hudFont);
  400.   }
  401. }  
  402.  
  403. /*------------------------------------------------------------------------*/
  404.  
  405. /*
  406.  * do_fade -- Smoothly fades the screen from white to black
  407.  *
  408.  */
  409. void
  410. do_fade(void)
  411. {
  412.   int i, r, g;
  413.   UWORD color[] = { 0x0fff };
  414.  
  415.   r = g = 15;
  416.  
  417.   for (i = 0; i < 15; i++) {
  418.     /* Red */
  419.     color[0] = ( (color[0] & 0x00ff) | ((--r) << 8) );
  420.     WaitTOF();
  421.     WaitTOF();
  422.     LoadRGB4(&myScreen->ViewPort, color, 1);
  423.     /* Green */
  424.     color[0] = ( (color[0] & 0x0f0f) | ((--g) << 4) );
  425.     WaitTOF();
  426.     LoadRGB4(&myScreen->ViewPort, color, 1);
  427.     /* Blue */
  428.     color[0]--;
  429.     WaitTOF();    
  430.     LoadRGB4(&myScreen->ViewPort, color, 1);
  431.   }
  432. }    
  433.  
  434.  
  435. /*------------------------------------------------------------------------*/
  436.  
  437. /*
  438.  * init_kbdrepeat -- Sets up structures for keyboard repeat modifying.
  439.  *                   Repeats are modified because keyboard repeating
  440.  *                   creates lag. Should perhaps read keys directly
  441.  *                   from keyboard.device..Shrug. This is still the
  442.  *                   easiest way I think.
  443.  */
  444. void
  445. init_kbdrepeat(void)
  446. {
  447.   struct shortprefs {
  448.     BYTE dummy1;
  449.     UBYTE dummy2;
  450.     UWORD dummy3;
  451.     struct timeval dummy4;
  452.     struct timeval keyRptDelay;
  453.   } myPrefs;
  454.  
  455.   GetPrefs( (struct Preferences *) &myPrefs, sizeof(struct shortprefs) );
  456.   oldrptdelay = myPrefs.keyRptDelay.tv_secs;
  457.  
  458.   if (!(inputPort = CreatePort( NULL, NULL )))
  459.     cleanExit( RETURN_WARN, "** Unable to create message port\n" );
  460.   if (!(inputReqBlk = (struct timerequest *) 
  461.        CreateExtIO(inputPort, sizeof(struct timerequest))))
  462.     cleanExit( RETURN_WARN, "** Unable to CreateExtIO()\n" ); 
  463.   if ((deviceopen = OpenDevice("input.device", NULL, 
  464.                                (struct IORequest *)inputReqBlk, NULL)))
  465.     cleanExit( RETURN_WARN, "** Unable to open input.device\n" );
  466.  
  467.   inputReqBlk->tr_node.io_Command = IND_SETTHRESH;
  468.   inputReqBlk->tr_time.tv_secs  = 0;
  469.   inputReqBlk->tr_time.tv_micro = myPrefs.keyRptDelay.tv_micro;
  470. }
  471.  
  472. /*------------------------------------------------------------------------*/
  473.  
  474. /*
  475.  * Main...
  476.  */
  477. void
  478. main(int argc, char *argv[])
  479. {
  480.   int   over = 0;
  481.   int   frameinfo[4] = { 0, 0, 0, 0 };
  482.   UWORD a_framerate;                   /* Actual framerate */
  483.  
  484. #ifdef CPU_USAGE
  485.   int    cpu_usage;
  486.   int    avg_cpu_usage  = 0;
  487.   int    topcounter     = 75;
  488.   int    top_cpu_usage  = 0;
  489.   int    top_cpu_usage2 = 0;
  490.   int    min_cpu_usage  = 100;
  491.   ULONG  e_freq, time1, time2; 
  492.   struct EClockVal eclock;
  493. #endif
  494.  
  495.   AShip           myShip, dummyShip;
  496.   BOOL            done = FALSE;
  497.   UWORD           CurBuffer;
  498.   ULONG           vb_signal;
  499.   extern UWORD    vb_counter;         /* This comes from our vblank server */
  500.   struct ViewPort *scrnVP;
  501.   struct Task     *my_task;
  502.  
  503.   /*
  504.    * Parse commandline for eventual options, and set default prefs.
  505.    */
  506.   set_prefs();
  507.  
  508.   /*
  509.    * Init everything..
  510.    */
  511.   CurBuffer = 1;
  512.   my_task   = FindTask(NULL);
  513.   vb_signal = init_VertBServer();
  514.   init_world();
  515.  
  516.   if (prefs.noserial == FALSE)
  517.     init_connection();
  518.  
  519.   init_map();
  520.   init_display();
  521.   init_font();
  522.   init_kbdrepeat();
  523.   init_sctables();
  524. #ifndef PURE_OS
  525.   init_writepixel(myBitMap[0]->BytesPerRow);
  526. #endif
  527.   init_points();
  528.   init_explosion();
  529.   init_ship(&myShip);
  530.  
  531.   /* This is just here for testing */
  532.   init_ship(&dummyShip);
  533.   dummyShip.shields = FALSE;
  534.   dummyShip.local   = FALSE;
  535.   dummyShip.next = World.players->next;
  536.   World.players->next = &dummyShip;
  537.   myShip.next = World.players->next;
  538.   World.players->next = &myShip;
  539.  
  540.   World.local_ship = &myShip;
  541.  
  542. #ifdef CPU_USAGE
  543.     if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) &tr, 0))
  544.       cleanExit( RETURN_WARN, "** Failed to open timer.device.\n");
  545.  
  546.     TimerBase = (struct Library *)tr.tr_node.io_Device;
  547.     /* Count how many e-ticks per screen update (50Hz) */
  548.     e_freq = (ReadEClock(&eclock) / 100) * APILOT_NFR;
  549. #endif    
  550.  
  551.   /*
  552.    * Set up needed structures for double-buffering..
  553.    */
  554.   if ((dbufport = CreateMsgPort()) == NULL)
  555.     cleanExit( RETURN_WARN, "** Unable to create message port\n" );
  556.  
  557.   scrnVP = &myScreen->ViewPort;
  558.   if ((myDBI = AllocDBufInfo( scrnVP )) == NULL)
  559.     cleanExit( RETURN_WARN, "** Unable to allocate DBufInfo\n" );
  560.  
  561.   myDBI->dbi_SafeMessage.mn_ReplyPort = dbufport;
  562.   myDBI->dbi_DispMessage.mn_ReplyPort = NULL;
  563.  
  564.   vb_counter = 0;
  565.  
  566.   /*
  567.    * Main loop...
  568.    */
  569.   while (!done) {
  570.  
  571.     a_framerate = vb_counter+1;
  572.     if (a_framerate < 5 ) 
  573.       frameinfo[a_framerate-1]++;
  574.  
  575. /*----------------------------------------------------*/
  576. /* This part is run on a higher priority to eliminate */
  577. /* flicker. This has VERY little impact on overall    */
  578. /* system performace but is needed because for some   */
  579. /* reason WaitTOF() isn't always very accurate on     */
  580. /* lower priorities.                                  */
  581. /*----------------------------------------------------*/
  582.     SetTaskPri(my_task, 30);
  583.     if (a_framerate > APILOT_NFR) {
  584.       over++;
  585.       WaitTOF();
  586.     }
  587.     Wait(vb_signal); 
  588.  
  589. #ifdef CPU_USAGE
  590.     ReadEClock(&eclock);
  591.     time1 = eclock.ev_lo;
  592. #endif
  593.  
  594.     WaitBlit();
  595.     ChangeVPBitMap(scrnVP, myBitMap[CurBuffer], myDBI);
  596.     SetTaskPri(my_task,0);
  597. /*---------------------------------------------------*/
  598.  
  599.     CurBuffer ^= 1; 
  600.     vb_counter = 0;
  601.  
  602.     /*
  603.      * Update everything...
  604.      */
  605.     move_points(CurBuffer, w_framerate); 
  606.     update_ship(&myShip, CurBuffer, w_framerate);
  607.     
  608.     /* Only for testing */
  609.     update_ship(&dummyShip, CurBuffer, w_framerate);
  610.  
  611.     update_cannons(&myShip, w_framerate);
  612.     update_fuelpods(w_framerate);
  613.     check_collisions();
  614.  
  615.     /* 
  616.      * Wait for the 'safe to write' message 
  617.      */
  618.     while (!GetMsg(dbufport)) Wait(1l<<(dbufport->mp_SigBit));
  619.  
  620.     /*
  621.      * Draw everything...
  622.      */
  623.     draw_ship(&myShip, &myRP[CurBuffer], CurBuffer);
  624.  
  625.     /* And testing again */
  626.     draw_ship(&dummyShip, &myRP[CurBuffer], CurBuffer);
  627.  
  628. #ifdef PURE_OS
  629.     draw_points(&myShip, &myRP[CurBuffer], CurBuffer, w_framerate); 
  630. #else
  631.     draw_points(&myShip, myBitMap[CurBuffer], CurBuffer, w_framerate); 
  632. #endif
  633.  
  634.     /* draw_map calls draw_hud */
  635.     draw_map(&myRP[CurBuffer], &myShip, CurBuffer, w_framerate);
  636.  
  637.  
  638. #ifdef CPU_USAGE
  639.     ReadEClock(&eclock);
  640.     time2 = eclock.ev_lo;
  641.  
  642.     cpu_usage = (abs(time2-time1)*(200/w_framerate))/e_freq % 300;
  643.     /* Average of 2 just to smooth it a little. */
  644.     avg_cpu_usage = (cpu_usage + avg_cpu_usage) / 2;
  645.  
  646.     if (cpu_usage > top_cpu_usage)
  647.       top_cpu_usage = cpu_usage;
  648.     if (cpu_usage > top_cpu_usage2)
  649.       top_cpu_usage2 = cpu_usage;
  650.     if (cpu_usage < min_cpu_usage)
  651.       min_cpu_usage = cpu_usage;
  652.     if (topcounter-- <= 0) {
  653.       topcounter    = 75;
  654.       top_cpu_usage = 0;
  655.     }
  656.  
  657.     if (cpu_meter) {
  658.       SetAPen(&myRP[CurBuffer], 0);
  659.       SetWriteMask(&myRP[CurBuffer], 1l);
  660.       RectFill( &myRP[CurBuffer], 70, 70,
  661.                                   370, 78 );
  662.       SetAPen(&myRP[CurBuffer], 1);
  663.       Move(&myRP[CurBuffer], 70 + top_cpu_usage, 70);
  664.       Draw(&myRP[CurBuffer], 70 + top_cpu_usage, 78);
  665.       RectFill( &myRP[CurBuffer], 70, 70,
  666.                                 70 + avg_cpu_usage, 78 );
  667.       Move(&myRP[CurBuffer], 70, 66);
  668.       Draw(&myRP[CurBuffer], 70, 82);
  669.       Move(&myRP[CurBuffer], 170, 66);
  670.       Draw(&myRP[CurBuffer], 170, 82);
  671.       Move(&myRP[CurBuffer], 270, 66);
  672.       Draw(&myRP[CurBuffer], 270, 82);
  673.     }
  674. #endif
  675.  
  676.     done = handleIDCMP(&myShip);
  677.   }
  678.  
  679.   printf("Over wanted framerate: %d frames.\n", over);
  680.   printf("50 fps : %d\n25 fps : %d\n16.7 fps : %d\n12.5fps : %d\n", 
  681.           frameinfo[0], frameinfo[1], frameinfo[2], frameinfo[3]);
  682.  
  683. #ifdef CPU_USAGE
  684.   printf("Max cpu usage during game: %d percent.\n", top_cpu_usage2 / 2);
  685.   printf("Min cpu usage during game: %d percent.\n", min_cpu_usage  / 2);
  686. #endif
  687.  
  688.   WaitBlit();
  689.   cleanExit( RETURN_OK, "" );
  690. }
  691.  
  692. /*------------------------------------------------------------------------*/
  693.  
  694. /*
  695.  * handleIDCMP -- Reads keyboard events and does what the user tells it
  696.  *                to do.
  697.  */
  698. BOOL 
  699. handleIDCMP(AShip *aShip)
  700. {
  701.   BOOL done = FALSE;
  702.   BOOL keyup;
  703.   ULONG class;
  704.   USHORT code;
  705.   USHORT qual;
  706.  
  707.   struct IntuiMessage *message;    
  708.   extern struct VertBData vertbdata;  /* From vertb.c */
  709.  
  710.  
  711.   /* Examine pending messages */
  712.   while( message = (struct IntuiMessage *)GetMsg(myWindow->UserPort) )
  713.   {
  714.     class = message->Class;  /* get all data we need from message */
  715.     code  = message->Code;
  716.     qual  = message->Qualifier;
  717.  
  718.     /* When we're through with a message, reply */
  719.     ReplyMsg( (struct Message *)message);
  720.  
  721.     /* See what events occurred */
  722.     keyup = (code & 0x80);
  723.  
  724.     switch( class ) {
  725.       case IDCMP_RAWKEY:
  726.         if(qual & IEQUALIFIER_RSHIFT)
  727.           aShip->thrusting = TRUE;
  728.         else
  729.           aShip->thrusting = FALSE;
  730.  
  731.         switch( 0x7F & code )
  732.         {
  733.           case RAWKEY_ENTER:
  734.             if (!keyup)
  735.               aShip->fireing = TRUE;
  736.             break;
  737.           case RAWKEY_A:
  738.             if (keyup)
  739.               aShip->turning = NO;
  740.             else
  741.               aShip->turning = LEFT;
  742.             break;
  743.           case RAWKEY_S:
  744.             if (keyup)
  745.               aShip->turning = NO;
  746.             else
  747.               aShip->turning = RIGHT;
  748.             break;
  749.           case RAWKEY_Q:  
  750.             inputReqBlk->tr_time.tv_secs = oldrptdelay;
  751.             DoIO((struct IORequest *) inputReqBlk);
  752.             done = TRUE;
  753.             break;
  754.           case RAWKEY_SPACE:
  755.             if (keyup)
  756.               aShip->shields = FALSE;
  757.             else
  758.               aShip->shields = TRUE;
  759.             break;
  760.           case RAWKEY_F:
  761.             if (keyup) {
  762.               aShip->fueling = FALSE;
  763.             } else {
  764.               World.hudon    = TRUE;
  765.               aShip->fueling = TRUE;
  766.               aShip->fpod    = NULL;
  767.             }
  768.             break;
  769. #ifdef CPU_USAGE
  770.           case RAWKEY_KP_STAR:
  771.             if (keyup)
  772.               cpu_meter ^= 1;
  773.             break;
  774. #endif
  775.           case RAWKEY_KP_MINUS:
  776.             if (keyup) {
  777.               if (w_framerate > 1) {
  778.                 World.framerate = --w_framerate;
  779.                 vertbdata.sigframe--;
  780.               }
  781.             }
  782.             break;
  783.           case RAWKEY_KP_PLUS:
  784.             if (keyup) {
  785.               if (w_framerate < 4) {
  786.                 World.framerate = ++w_framerate;
  787.                 vertbdata.sigframe++;
  788.               }
  789.             }
  790.             break;
  791.           default:
  792.             break;
  793.         }
  794.         break;
  795.       case IDCMP_ACTIVEWINDOW:
  796.         /* 1000 Should be enough to prevent repeat. */
  797.         inputReqBlk->tr_time.tv_secs = 1000;
  798.         DoIO((struct IORequest *) inputReqBlk);
  799.         break;
  800.       case IDCMP_INACTIVEWINDOW:
  801.         inputReqBlk->tr_time.tv_secs = oldrptdelay;
  802.         DoIO((struct IORequest *) inputReqBlk);
  803.         break;
  804.       default:
  805.         break;
  806.     }
  807.   }
  808.   return(done);
  809. }
  810.  
  811. /*------------------------------------------------------------------------*/
  812.  
  813. /*
  814.  * cleanExit -- Closes windows, screens etc. and tries to exit
  815.  *              gracefully.
  816.  */
  817. void 
  818. cleanExit( LONG returnValue, char *fmt, ... )
  819. {
  820.   int i;
  821.   va_list argp;
  822.  
  823.   va_start(argp, fmt);
  824.   vfprintf (stderr, fmt, argp);
  825.   va_end(argp);
  826.  
  827.   remove_VertBServer();
  828.   if (deviceopen == 0) CloseDevice((struct IORequest *) inputReqBlk);
  829.   if (inputReqBlk)     DeleteExtIO((struct IORequest *) inputReqBlk);
  830.   if (inputPort)       DeletePort( inputPort );
  831.   if (myDBI)           FreeDBufInfo( myDBI );
  832.   if (myWindow)        CloseWindow( myWindow );
  833.   if (myScreen)        CloseScreen( myScreen );
  834.   if (hudFont)         CloseFont(hudFont);
  835.   if (!prefs.noserial) close_connection();
  836.  
  837. #ifdef CPU_USAGE
  838.   if (TimerBase)       CloseDevice((struct IORequest *) &tr);
  839. #endif
  840.  
  841.   if (dbufport) {
  842.     /* Cleanup any pending messages */
  843.     while (GetMsg(dbufport));
  844.     DeleteMsgPort(dbufport);
  845.   }
  846.  
  847.   if (World.shld_bm != NULL)
  848.     FreeBitMap( World.shld_bm );
  849.  
  850.   for (i = 0; i < MY_BUFFERS; i++) {
  851.     if (myBitMap[i] != NULL)
  852.       FreeBitMap( myBitMap[i] );
  853.   }
  854.   exit(returnValue);
  855. }
  856.  
  857. /*------------------------------------------------------------------------*/
  858.