home *** CD-ROM | disk | FTP | other *** search
/ Total Meltdown / dukenukemtotalmeltdown.img / util / dukectrl / launch.c < prev    next >
C/C++ Source or Header  |  1996-02-20  |  12KB  |  554 lines

  1. // Launch program for External Controllers
  2. // This External Control API should work with all "Build" type
  3. // 3DRealm games with little modification.
  4. //
  5. // Specific implementation detail about a controller is left
  6. // for the user to insert code about their particular device
  7. //
  8. // This example controller supports the mouse as its external
  9. // device.  This is just an example
  10. //
  11. // This program was compiled and created with Borland C/C++ 3.1, but just
  12. // about any 16-bit compiler can be used.
  13. //
  14. // If you have any questions on integrating your device with 3DRealms games
  15. // you can contact me, Mark Dochtermann at:
  16. //
  17. // 76746,3357 on CompuServe or
  18. // paradigm @ metronet.com
  19. //
  20. // 02/19/96 Example driver creation.
  21.  
  22. // include files
  23. #include <conio.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <dos.h>
  27. #include <string.h>
  28. #include <process.h>
  29. #include <stdarg.h>
  30. #include <bios.h>
  31. #include <time.h>
  32. #include <float.h>
  33.  
  34. #include "types.h"
  35. #include "external.h"
  36. #include "function.h"
  37.  
  38. #define CONTROL_STACKSIZE    (2048)
  39. #define CONTROL_SAFETYMARGIN (8)
  40.  
  41. typedef enum
  42.    {
  43.    axis_up,
  44.    axis_down,
  45.    axis_left,
  46.    axis_right
  47.    } axisdirection;
  48.  
  49. typedef enum
  50.    {
  51.    analog_turning=0,
  52.    analog_strafing=1,
  53.    analog_lookingupanddown=2,
  54.    analog_elevation=3,
  55.    analog_rolling=4,
  56.    analog_moving=5,
  57.    analog_maxtype
  58.    } analogcontrol;
  59.  
  60. union REGS inregs, outregs;
  61. struct SREGS segregs;
  62.  
  63. static ExternalControlInfo control;
  64. static boolean control_started = false;
  65. void interrupt (*oldcontrolvector) (void);
  66. void interrupt CONTROL_ISR (void);
  67. static char * control_stack;
  68. static unsigned short control_stacksegment;
  69. static unsigned short control_stackpointer;
  70. static unsigned short old_stacksegment;
  71. static unsigned short old_stackpointer;
  72.  
  73. #define DUKECONTROLID 0xdead
  74. #define MouseInt 0x33
  75. #define ResetMouse       0
  76. #define GetMouseButtons  3
  77. #define GetMouseDelta    11
  78.  
  79. #define FIRE (1<<0)
  80. #define OPEN (1<<1)
  81. #define AIMUP (1<<2)
  82. #define AIMDOWN (1<<3)
  83. #define RUN (1<<4)
  84. #define INVENTORYLEFT (1<<5)
  85. #define INVENTORYRIGHT (1<<6)
  86. #define INVENTORY (1<<7)
  87.  
  88. /*
  89. =================
  90. =
  91. = CheckParm
  92. =
  93. = Checks for the given parameter in the program's command line arguments
  94. =
  95. = Returns the argument number (1 to argc-1) or 0 if not present
  96. =
  97. =================
  98. */
  99.  
  100. int CheckParm (char *check)
  101.    {
  102.    char  i;
  103.    char  *parm;
  104.    char  tempstring[128];
  105.    char  delims[4] = {'\\','-','/',(char)NULL};
  106.  
  107.    for (i = 1;i<_argc;i++)
  108.       {
  109.       strcpy(tempstring,_argv[i]);
  110.       parm = strtok(tempstring,&delims[0]);
  111.       if (parm == NULL)
  112.          continue;
  113.  
  114.       if (!stricmp(check,parm) )
  115.          return i;
  116.       }
  117.    return 0;
  118.    }
  119.  
  120. //******************************************************************************
  121. //
  122. // MOUSE_GetDelta
  123. //
  124. // Gets the amount that the mouse has moved from the mouse driver.
  125. //
  126. //******************************************************************************
  127.  
  128. void MOUSE_GetDelta( int32*x, int32*y  )
  129.    {
  130.    inregs.x.ax = GetMouseDelta;
  131.    int86( MouseInt, &inregs, &outregs );
  132.  
  133.    *x = ( int32 )((int16)outregs.x.cx);
  134.    *y = ( int32 )((int16)outregs.x.dx);
  135.    }
  136.  
  137. //******************************************************************************
  138. //
  139. // MOUSE_GetButtons ()
  140. //
  141. //******************************************************************************
  142.  
  143. int32 MOUSE_GetButtons( void )
  144.    {
  145.    inregs.x.ax = GetMouseButtons;
  146.    int86( MouseInt, &inregs, &outregs );
  147.  
  148.    return( (int32)outregs.h.bl );
  149.    }
  150.  
  151.  
  152. //******************************************************************************
  153. //
  154. // MOUSE_Init ()
  155. //
  156. // Detects and sets up the mouse.
  157. //
  158. //******************************************************************************
  159.  
  160. boolean MOUSE_Init( void )
  161.    {
  162.    inregs.x.ax = ResetMouse;
  163.    int86( MouseInt, &inregs, &outregs );
  164.  
  165.    return( outregs.x.ax == 0xffff );
  166.    }
  167.  
  168. //******************************************************************************
  169. //
  170. // MOUSE_Shutdown ()
  171. //
  172. // Shutsdown the mouse
  173. //
  174. //******************************************************************************
  175.  
  176. void MOUSE_Shutdown( void )
  177.    {
  178.    }
  179.  
  180. /*
  181. =================
  182. =
  183. = InitializeDevice
  184. =
  185. = This function intializes your device.
  186. =
  187. = Returns 0 upon success, any other number on failure
  188. =
  189. =================
  190. */
  191.  
  192. int32 InitializeDevice( void )
  193.    {
  194.    int32 i;
  195.    boolean status;
  196.  
  197.    //
  198.    // Setup our mappings for the game
  199.    //
  200.  
  201.    //
  202.    // We have two axes on the mouse so we only
  203.    // need to define two axes
  204.    //
  205.  
  206.    control.analogaxesmap[0] = analog_turning;
  207.    control.analogaxesmap[1] = analog_moving;
  208.  
  209.    //
  210.    // the mouse works best as an analog device,
  211.    // so we won't do any digital mappings of the
  212.    // axes.
  213.    //
  214.  
  215.    //
  216.    // Setup our default button mappings
  217.    // the way the mouse is set up, we get
  218.    // LMB in bit 0, RMB in bit 1 and MMB in bit 2
  219.    //
  220.  
  221.    // map single clicked buttons
  222.    control.buttonmap[0][0] = gamefunc_Fire;
  223.    control.buttonmap[1][0] = gamefunc_Strafe;
  224.    control.buttonmap[2][0] = gamefunc_Move_Forward;
  225.  
  226.    // map double clicked buttons
  227.    control.buttonmap[1][1] = gamefunc_Open;
  228.  
  229.    // see if our device is available
  230.  
  231.    status = MOUSE_Init();
  232.    if (status)
  233.       {
  234.       printf("Mouse has been initialized\n");
  235.       return 0;
  236.       }
  237.    printf("ERROR - Mouse not found or unavailable\n");
  238.    return -1;
  239.    }
  240.  
  241. /*
  242. =================
  243. =
  244. = ShutdownDevice
  245. =
  246. = This function shutsdown your device.
  247. =
  248. =================
  249. */
  250. void ShutdownDevice( void )
  251.    {
  252.    MOUSE_Shutdown();
  253.    }
  254.  
  255. /*
  256. =================
  257. =
  258. = GetDeviceInput
  259. =
  260. = This function querys your device and gets it's input
  261. =
  262. =================
  263. */
  264. void GetDeviceInput( void )
  265.    {
  266.    //
  267.    // get movement info
  268.    //
  269.    MOUSE_GetDelta( &control.axes[0], &control.axes[1] );
  270.  
  271.    // perform some rudimentary filtering
  272.    if (abs(control.axes[0])>abs(control.axes[1]))
  273.       control.axes[1]/=3;
  274.    else
  275.       control.axes[0]/=3;
  276.  
  277.    // scale up our values into the game domain
  278.    control.axes[0]*=32;
  279.    control.axes[1]*=96;
  280.  
  281.    //
  282.    // get button info
  283.    //
  284.    control.buttonstate = MOUSE_GetButtons();
  285.    }
  286.  
  287. /*
  288. =============
  289. =
  290. = SetupCONTROL
  291. =
  292. =============
  293. */
  294.  
  295. void SetupCONTROL ( void )
  296.    {
  297.     unsigned char far *vectorptr;
  298.    short vector;
  299.    char * topofstack;
  300.    int i;
  301.  
  302.  
  303.     if ((i = CheckParm("-vector")) != 0)
  304.       {
  305.       vector = sscanf ("0x%x",_argv[i+1]);
  306.       goto gotit;
  307.       }
  308.  
  309.      /* Get an interrupt vector */
  310.    for (vector = 0x60 ; vector <= 0x66 ; vector++)
  311.       {
  312.         vectorptr = *(unsigned char far * far *)(vector*4);
  313.         if ( !vectorptr || *vectorptr == 0xcf )
  314.             break;
  315.        }
  316.    if (vector == 0x67)
  317.        {
  318.       printf ("Warning: no NULL or iret interrupt vectors were found between 0x60 and 0x65\n"
  319.               "You can specify a vector with the -vector 0x<num> parameter.\n"
  320.               "Press a key to continue.\n");
  321.        getch ();
  322.       printf ("Using default vector 0x66\n");
  323.       vector = 0x66;
  324.         }
  325. gotit:
  326.     control.intnum = vector;
  327.  
  328.    // allocate the gamecontrol stack
  329.  
  330.    control_stack = malloc(CONTROL_STACKSIZE);
  331.  
  332.    // check to see if the malloc worked
  333.    if (!control_stack)
  334.       {
  335.       printf("ERROR: could not malloc stack\n");
  336.       }
  337.  
  338.    // Calculate top of stack
  339.  
  340.    topofstack = control_stack + CONTROL_STACKSIZE - CONTROL_SAFETYMARGIN;
  341.  
  342.    // Determine stack segment and pointer
  343.  
  344.    control_stacksegment = FP_SEG( (char huge *)topofstack );
  345.    control_stackpointer = FP_OFF( (char huge *)topofstack );
  346.  
  347.    // hook the vector for the game
  348.  
  349.     oldcontrolvector = getvect (control.intnum);
  350.     setvect (control.intnum, CONTROL_ISR);
  351.    control_started = true;
  352.    }
  353.  
  354.  
  355. /*
  356. =============
  357. =
  358. = ShutdownCONTROL
  359. =
  360. =============
  361. */
  362.  
  363. void ShutdownCONTROL ( void )
  364.    {
  365.     if (control_started)
  366.       {
  367.       control_started = false;
  368.         setvect (control.intnum,oldcontrolvector);
  369.       free ( control_stack );
  370.       }
  371.    }
  372.  
  373. /*
  374. =============
  375. =
  376. = CONTROL_ISR
  377. =
  378. =============
  379. */
  380.  
  381. #define GetStack(a,b) \
  382.    {                  \
  383.    *a = _SS;          \
  384.    *b = _SP;          \
  385.    }
  386. #define SetStack(a,b) \
  387.    {                  \
  388.    _SS=a;             \
  389.    _SP=b;             \
  390.    }
  391.  
  392. void interrupt CONTROL_ISR (void)
  393.     {
  394.    //
  395.    // Get current stack
  396.    //
  397.  
  398.    GetStack( &old_stacksegment, &old_stackpointer );
  399.  
  400.    //
  401.    // Set the local stack
  402.    //
  403.  
  404.    SetStack( control_stacksegment, control_stackpointer );
  405.  
  406.    if (control.command == EXTERNAL_GetInput)
  407.       {
  408.       GetDeviceInput();
  409.       }
  410.  
  411.    //
  412.    // Restore the old stack
  413.    //
  414.  
  415.    SetStack( old_stacksegment, old_stackpointer );
  416.    }
  417.  
  418. /*
  419. =============
  420. =
  421. = LaunchGAME
  422. =
  423. =============
  424. */
  425.  
  426. void LaunchGAME ( int pause )
  427. {
  428.     char    *newargs[39];
  429.    char  *launchname;
  430.     char    adrstring[10];
  431.     long      flatadr;
  432.     int argnum = 1;
  433.     int i,j;
  434.  
  435.     i = CheckParm("launch");
  436.     if (i != 0)
  437.       {
  438.       i++;
  439.       launchname = _argv[i];
  440.       i++;
  441.       }
  442.    else
  443.       {
  444.       printf("No program to launch\n");
  445.       return;
  446.       }
  447.  
  448.     SetupCONTROL ();
  449.  
  450.    //
  451.    // if we did not successfully set up our interrupt get out of here
  452.    //
  453.    if (!control_started)
  454.       return;
  455.  
  456.    // build the argument list for the game
  457.    // adding all previous command lines to be passed to the main game
  458.  
  459.    // i initialized from above
  460.    for (;i<_argc;i++)
  461.       {
  462.       newargs [argnum++] = _argv[i];
  463.       }
  464.  
  465.     newargs [argnum++] = "-" EXTERNALPARM;
  466.  
  467.     /* Add address of gamecontrol structure */
  468.  
  469.     flatadr = (long)_DS*16 + (unsigned)&control;
  470.     sprintf (adrstring,"%lu",flatadr);
  471.     newargs [argnum++] = adrstring;
  472.  
  473.     newargs [argnum] = NULL;
  474.  
  475. // Make sure arg 0 is correct, if we want to dump the arguments
  476.  
  477.     newargs [0] = launchname;
  478.  
  479.    if (pause==1)
  480.       {
  481.       for (i = 0; i < argnum; i++)
  482.          printf ("  arg %d = %s\n", i, newargs [i]);
  483.  
  484.       printf ("\nPress ESC to abort, or any other key to continue...");
  485.       if (getch () == 0x1b)
  486.          {
  487.          printf ("\n\n");
  488.          ShutdownCONTROL();
  489.          return;
  490.          }
  491.       }
  492.    if (spawnvp ( P_WAIT, launchname, newargs) != 0)
  493.       {
  494.       if (errno!=0)
  495.          printf("%s\n%d\n",strerror(errno),errno);
  496.       }
  497.     printf ("\nReturned from %s\n\n",launchname);
  498.  
  499.    ShutdownCONTROL();
  500.     }
  501.  
  502. /*
  503. =============
  504. =
  505. = main
  506. =
  507. =============
  508. */
  509.  
  510. void main( void )
  511.    {
  512.    int32 i;
  513.  
  514.    // welcome the user
  515.    printf ("External Launch for 3DRealms games.\n");
  516.    printf ("Duke Nukem 3D implementation.\n");
  517.    printf ("Written by Mark Dochtermann.\n");
  518.    printf ("Version 1.0\n");
  519.  
  520.    // clear out control structure
  521.    memset(&control,0,sizeof(control));
  522.  
  523.    control.id=DUKECONTROLID;
  524.  
  525.    //
  526.    // clear all assigments
  527.    //
  528.  
  529.    // clear all button mappings
  530.    for (i=0;i<MAXEXTERNALBUTTONS;i++)
  531.       {
  532.       control.buttonmap[i][0] = EXTERNALBUTTONUNDEFINED;
  533.       control.buttonmap[i][1] = EXTERNALBUTTONUNDEFINED;
  534.       }
  535.  
  536.    // clear all axis mappings
  537.    for (i=0;i<MAXEXTERNALAXES;i++)
  538.       {
  539.       control.analogaxesmap[i] = EXTERNALAXISUNDEFINED;
  540.       control.digitalaxesmap[i][0] = EXTERNALAXISUNDEFINED;
  541.       control.digitalaxesmap[i][1] = EXTERNALAXISUNDEFINED;
  542.       }
  543.  
  544.    // try to initialize the device
  545.    if (InitializeDevice())
  546.       {
  547.       exit(0);
  548.       }
  549.    // launch the game
  550.    LaunchGAME ( 1 );
  551.    // we are back from the game, so clean up and exit
  552.    ShutdownDevice();
  553.    }
  554.