home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / apilot.lha / APilot / APilot_Ser / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-03  |  25.8 KB  |  885 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. #include "common.h"
  53. #include "vertb.h"
  54. #include "map.h"
  55. #include "prefs.h"
  56.  
  57. /*------------------------------------------------------------------------*/
  58.  
  59. /* Disable ctrl-c handling */
  60. void __regargs __chkabort(void);
  61. void __regargs __chkabort(void) { return; }
  62.  
  63. /*------------------------------------------------------------------------*/
  64.  
  65. char *version = "$VER: APilot_Ser 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, remoteShip;
  496.   UWORD           CurBuffer;
  497.   ULONG           vb_signal;
  498.   extern UWORD    vb_counter;         /* This comes from our vblank server */
  499.   struct ViewPort *scrnVP;
  500.   struct Task     *my_task;
  501.  
  502.   /*
  503.    * Parse commandline for eventual options, and set default prefs.
  504.    */
  505.   set_prefs();
  506.  
  507.   /*
  508.    * Init everything..
  509.    */
  510.   CurBuffer = 1;
  511.   my_task   = FindTask(NULL);
  512.   vb_signal = init_VertBServer();
  513.   init_world();
  514.  
  515.   if (prefs.noserial == FALSE)
  516.     init_connection();
  517.  
  518.   init_map();
  519.   init_display();
  520.   init_font();
  521.   init_kbdrepeat();
  522.   init_sctables();
  523. #ifndef PURE_OS
  524.   init_writepixel(myBitMap[0]->BytesPerRow);
  525. #endif
  526.   init_points();
  527.   init_explosion();
  528.   if (World.host) {
  529.     init_ship(&myShip);
  530.     init_ship(&remoteShip);
  531.   } else {
  532.     init_ship(&remoteShip);
  533.     init_ship(&myShip);
  534.   }  
  535.   remoteShip.shields = FALSE;
  536.   remoteShip.local   = FALSE;
  537.  
  538.   remoteShip.next = World.players->next;
  539.   World.players->next = &remoteShip;
  540.   myShip.next = World.players->next;
  541.   World.players->next = &myShip;
  542.  
  543.   World.local_ship  = &myShip;
  544.   World.remote_ship = &remoteShip;
  545.  
  546.   /*
  547.    * Send this once so the loop can get started.
  548.    */
  549.   send_local(APILOT_NFR);
  550.  
  551.  
  552. #ifdef CPU_USAGE
  553.     if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *) &tr, 0))
  554.       cleanExit( RETURN_WARN, "** Failed to open timer.device.\n");
  555.  
  556.     TimerBase = (struct Library *)tr.tr_node.io_Device;
  557.     /* Count how many e-ticks per screen update (50Hz) */
  558.     e_freq = (ReadEClock(&eclock) / 100) * APILOT_NFR;
  559. #endif    
  560.  
  561.   /*
  562.    * Set up needed structures for double-buffering..
  563.    */
  564.   if ((dbufport = CreateMsgPort()) == NULL)
  565.     cleanExit( RETURN_WARN, "** Unable to create message port\n" );
  566.  
  567.   scrnVP = &myScreen->ViewPort;
  568.   if ((myDBI = AllocDBufInfo( scrnVP )) == NULL)
  569.     cleanExit( RETURN_WARN, "** Unable to allocate DBufInfo\n" );
  570.  
  571.   myDBI->dbi_SafeMessage.mn_ReplyPort = dbufport;
  572.   myDBI->dbi_DispMessage.mn_ReplyPort = NULL;
  573.  
  574.   vb_counter = 0;
  575.  
  576.   /*
  577.    * Main loop...
  578.    */
  579.   while (TRUE) {
  580.  
  581.     a_framerate = vb_counter+1;
  582.     if (a_framerate < 5 ) 
  583.       frameinfo[a_framerate-1]++;
  584.  
  585. /*----------------------------------------------------*/
  586. /* This part is run on a higher priority to eliminate */
  587. /* flicker. This has VERY little impact on overall    */
  588. /* system performace but is needed because for some   */
  589. /* reason WaitTOF() isn't always very accurate on     */
  590. /* lower priorities.                                  */
  591. /*----------------------------------------------------*/
  592.     SetTaskPri(my_task, 30); 
  593.     if (a_framerate > APILOT_NFR) {
  594.       over++;
  595.       WaitTOF();
  596.     }
  597.     Wait(vb_signal);
  598.  
  599. #ifdef CPU_USAGE
  600.     ReadEClock(&eclock);
  601.     time1 = eclock.ev_lo;
  602. #endif
  603.  
  604.     WaitBlit();
  605.     ChangeVPBitMap(scrnVP, myBitMap[CurBuffer], myDBI);
  606.     SetTaskPri(my_task,0); 
  607. /*---------------------------------------------------*/
  608.  
  609.     CurBuffer ^= 1; 
  610.     vb_counter = 0;
  611.  
  612.     /*
  613.      * Update everything...
  614.      */
  615.     move_points(CurBuffer, w_framerate);  
  616.     update_ship(&myShip, CurBuffer, w_framerate); 
  617.  
  618.     /*
  619.      * Read what the remote ship is doing and then
  620.      * update it.
  621.      */
  622.     if (update_remote(CurBuffer, w_framerate) == TRUE) {
  623.       printf("Remote quit.\n");
  624.       break;
  625.     }
  626.  
  627.     update_cannons(&myShip, w_framerate); 
  628.     update_fuelpods(w_framerate);
  629.     check_collisions();
  630.  
  631.     /*
  632.      * Now we read what the local ship is doing and then send
  633.      * it over to the remote player.
  634.      */
  635.     if (handleIDCMP() == TRUE) {
  636.       send_quit();
  637.       break;
  638.     }
  639.     send_local(w_framerate);
  640.  
  641.     /* 
  642.      * Wait for the 'safe to write' message 
  643.      */
  644.     while (!GetMsg(dbufport)) Wait(1l<<(dbufport->mp_SigBit));
  645.  
  646.     /*
  647.      * Draw everything...
  648.      */
  649.     draw_ship(&myShip, &myRP[CurBuffer], CurBuffer);
  650.     draw_ship(&remoteShip, &myRP[CurBuffer], CurBuffer);
  651.  
  652. #ifdef PURE_OS
  653.     draw_points(&myShip, &myRP[CurBuffer], CurBuffer, w_framerate); 
  654. #else
  655.     draw_points(&myShip, myBitMap[CurBuffer], CurBuffer, w_framerate); 
  656. #endif
  657.  
  658.     /* draw_map calls draw_hud */
  659.     draw_map(&myRP[CurBuffer], &myShip, CurBuffer, w_framerate);
  660.  
  661.  
  662. #ifdef CPU_USAGE
  663.     ReadEClock(&eclock);
  664.     time2 = eclock.ev_lo;
  665.  
  666.     cpu_usage = (abs(time2-time1)*(200/w_framerate))/e_freq % 300;
  667.     /* Average of 2 just to smooth it a little. */
  668.     avg_cpu_usage = (cpu_usage + avg_cpu_usage) / 2;
  669.  
  670.     if (cpu_usage > top_cpu_usage)
  671.       top_cpu_usage = cpu_usage;
  672.     if (cpu_usage > top_cpu_usage2)
  673.       top_cpu_usage2 = cpu_usage;
  674.     if (cpu_usage < min_cpu_usage)
  675.       min_cpu_usage = cpu_usage;
  676.     if (topcounter-- <= 0) {
  677.       topcounter    = 75;
  678.       top_cpu_usage = 0;
  679.     }
  680.  
  681.     if (cpu_meter) {
  682.       SetAPen(&myRP[CurBuffer], 0);
  683.       SetWriteMask(&myRP[CurBuffer], 1l);
  684.       RectFill( &myRP[CurBuffer], 70, 70,
  685.                                   370, 78 );
  686.       SetAPen(&myRP[CurBuffer], 1);
  687.       Move(&myRP[CurBuffer], 70 + top_cpu_usage, 70);
  688.       Draw(&myRP[CurBuffer], 70 + top_cpu_usage, 78);
  689.       RectFill( &myRP[CurBuffer], 70, 70,
  690.                                 70 + avg_cpu_usage, 78 );
  691.       Move(&myRP[CurBuffer], 70, 66);
  692.       Draw(&myRP[CurBuffer], 70, 82);
  693.       Move(&myRP[CurBuffer], 170, 66);
  694.       Draw(&myRP[CurBuffer], 170, 82);
  695.       Move(&myRP[CurBuffer], 270, 66);
  696.       Draw(&myRP[CurBuffer], 270, 82);
  697.     }
  698. #endif
  699.  
  700.   }
  701.  
  702.   printf("Over wanted framerate: %d frames.\n", over);
  703.   printf("50 fps : %d\n25 fps : %d\n16.7 fps : %d\n12.5fps : %d\n", 
  704.           frameinfo[0], frameinfo[1], frameinfo[2], frameinfo[3]);
  705.  
  706. #ifdef CPU_USAGE
  707.   printf("Max cpu usage during game: %d percent.\n", top_cpu_usage2 / 2);
  708.   printf("Min cpu usage during game: %d percent.\n", min_cpu_usage  / 2);
  709. #endif
  710.  
  711.   WaitBlit();
  712.   cleanExit( RETURN_OK, "" );
  713. }
  714.  
  715. /*------------------------------------------------------------------------*/
  716.  
  717. /*
  718.  * handleIDCMP -- Reads keyboard events and does what the user tells it
  719.  *                to do.
  720.  */
  721. BOOL 
  722. handleIDCMP(void)
  723. {
  724.   BOOL done = FALSE;
  725.   BOOL keyup;
  726.   ULONG class;
  727.   USHORT code;
  728.   USHORT qual;
  729.   AShip *ship = World.local_ship;
  730.  
  731.   struct IntuiMessage *message;    
  732.   extern struct VertBData vertbdata;  /* From vertb.c */
  733.  
  734.   /* Examine pending messages */
  735.   while( message = (struct IntuiMessage *)GetMsg(myWindow->UserPort) )
  736.   {
  737.     class = message->Class;  /* get all data we need from message */
  738.     code  = message->Code;
  739.     qual  = message->Qualifier;
  740.  
  741.     /* When we're through with a message, reply */
  742.     ReplyMsg( (struct Message *)message);
  743.  
  744.     /* See what events occurred */
  745.     keyup = (code & 0x80);
  746.  
  747.     switch( class ) {
  748.       case IDCMP_RAWKEY:
  749.         if(qual & IEQUALIFIER_RSHIFT) {
  750.           ship->thrusting = TRUE;
  751.         } else {
  752.           ship->thrusting = FALSE;
  753.         }
  754.         switch( 0x7F & code )
  755.         {
  756.           case RAWKEY_ENTER:
  757.             if (!keyup) {
  758.               ship->fireing = TRUE;
  759.             }
  760.             break;
  761.           case RAWKEY_A:
  762.             if (keyup)
  763.               ship->turning = NO;
  764.             else 
  765.               ship->turning = LEFT;
  766.             break;
  767.           case RAWKEY_S:
  768.             if (keyup)
  769.               ship->turning = NO;
  770.             else
  771.               ship->turning = RIGHT;
  772.             break;
  773.           case RAWKEY_Q:  
  774.             done = TRUE;
  775.             break;
  776.           case RAWKEY_SPACE:
  777.             if (keyup)
  778.               ship->shields = FALSE;
  779.             else
  780.               ship->shields = TRUE;
  781.             break;
  782.           case RAWKEY_F:
  783.             if (keyup) {
  784.               ship->fueling = FALSE;
  785.             } else {
  786.               World.hudon   = TRUE;
  787.               ship->fueling = TRUE;
  788.               ship->fpod    = NULL;
  789.             }
  790.             break;
  791. #ifdef CPU_USAGE
  792.           case RAWKEY_KP_STAR:
  793.             if (keyup)
  794.               cpu_meter ^= 1;
  795.             break;
  796. #endif
  797.           case RAWKEY_KP_MINUS:
  798.             if (keyup) {
  799.               if (w_framerate > 1) {
  800.                 World.framerate = --w_framerate;
  801.                 vertbdata.sigframe--;
  802.               }
  803.             }
  804.             break;
  805.           case RAWKEY_KP_PLUS:
  806.             if (keyup) {
  807.               if (w_framerate < 4) {
  808.                 World.framerate = ++w_framerate;
  809.                 vertbdata.sigframe++;
  810.               }
  811.             }
  812.             break;
  813.           default:
  814.             break;
  815.         }
  816.         break;
  817.       case IDCMP_ACTIVEWINDOW:
  818.         /* 1000 Should be enough to prevent repeat. */
  819.         inputReqBlk->tr_time.tv_secs = 1000;
  820.         DoIO((struct IORequest *) inputReqBlk);
  821.         break;
  822.       case IDCMP_INACTIVEWINDOW:
  823.         inputReqBlk->tr_time.tv_secs = oldrptdelay;
  824.         DoIO((struct IORequest *) inputReqBlk);
  825.         break;
  826.       default:
  827.         break;
  828.     }
  829.   }
  830.   return(done);
  831. }
  832.  
  833. /*------------------------------------------------------------------------*/
  834.  
  835. /*
  836.  * cleanExit -- Closes windows, screens etc. and tries to exit
  837.  *              gracefully.
  838.  */
  839. void 
  840. cleanExit( LONG returnValue, char *fmt, ... )
  841. {
  842.   int i;
  843.   va_list argp;
  844.  
  845.   va_start(argp, fmt);
  846.   vfprintf (stderr, fmt, argp);
  847.   va_end(argp);
  848.  
  849.   remove_VertBServer();
  850.   if (deviceopen == 0) {
  851.     /* Restore old repeat delay. */
  852.     inputReqBlk->tr_time.tv_secs = oldrptdelay;
  853.     DoIO((struct IORequest *) inputReqBlk);
  854.     CloseDevice((struct IORequest *) inputReqBlk);
  855.   }
  856.   if (inputReqBlk)     DeleteExtIO((struct IORequest *) inputReqBlk);
  857.   if (inputPort)       DeletePort( inputPort );
  858.   if (myDBI)           FreeDBufInfo( myDBI );
  859.   if (myWindow)        CloseWindow( myWindow );
  860.   if (myScreen)        CloseScreen( myScreen );
  861.   if (hudFont)         CloseFont(hudFont);
  862.   if (!prefs.noserial) close_connection();
  863.  
  864. #ifdef CPU_USAGE
  865.   if (TimerBase)       CloseDevice((struct IORequest *) &tr);
  866. #endif
  867.  
  868.   if (dbufport) {
  869.     /* Cleanup any pending messages */
  870.     while (GetMsg(dbufport));
  871.     DeleteMsgPort(dbufport);
  872.   }
  873.  
  874.   if (World.shld_bm != NULL)
  875.     FreeBitMap( World.shld_bm );
  876.  
  877.   for (i = 0; i < MY_BUFFERS; i++) {
  878.     if (myBitMap[i] != NULL)
  879.       FreeBitMap( myBitMap[i] );
  880.   }
  881.   exit(returnValue);
  882. }
  883.  
  884. /*------------------------------------------------------------------------*/
  885.