home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / BATTLE.ZIP / INSTALL.ZIP / INPUT.C < prev    next >
C/C++ Source or Header  |  1996-04-06  |  19KB  |  682 lines

  1.  
  2. // INPUT.C - Library Module
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17.  
  18. #include "input.h"
  19.  
  20. // G L O B A L S  ////////////////////////////////////////////////////////////
  21.  
  22. void (_interrupt _far *Old_Keyboard_ISR)();  // holds old keyboard interrupt handler
  23.  
  24. int raw_scan_code=0;  // the global keyboard scan code
  25.  
  26. // this holds the keyboard state table which tracks the state of every key
  27. // on the keyboard
  28.  
  29. int keyboard_state[128];
  30.  
  31. // this tracks the number of keys that are currently pressed, helps
  32. // with keyboard testing logic
  33.  
  34. int keys_active = 0;
  35.  
  36. // these values hold the maximum, minimum and neutral joystick values for
  37. // both joysticks
  38.  
  39. unsigned int joystick_1_max_x,
  40.              joystick_1_max_y,
  41.              joystick_1_min_x,
  42.              joystick_1_min_y,
  43.              joystick_1_neutral_x,
  44.              joystick_1_neutral_y,
  45.  
  46.              joystick_2_max_x,
  47.              joystick_2_max_y,
  48.              joystick_2_min_x,
  49.              joystick_2_min_y,
  50.              joystick_2_neutral_x,
  51.              joystick_2_neutral_y;
  52.  
  53. // F U N C T I O N S /////////////////////////////////////////////////////////
  54.  
  55. unsigned char Get_Key(void)
  56. {
  57. // test if a key press has been buffered by system and if so, return the ASCII
  58. // value of the key, otherwise return 0
  59.  
  60. if (_bios_keybrd(_KEYBRD_READY))
  61.  return((unsigned char)_bios_keybrd(_KEYBRD_READ));
  62. else return(0);
  63.  
  64. } // end Get_Key
  65.  
  66. //////////////////////////////////////////////////////////////////////////////
  67.  
  68. unsigned int Get_Shift_State(unsigned int mask)
  69. {
  70. // return the shift state of the keyboard logically ANDed with the sent mask
  71.  
  72. return(mask & _bios_keybrd(_KEYBRD_SHIFTSTATUS));
  73.  
  74. } // end Get_Shift_State
  75.  
  76. //////////////////////////////////////////////////////////////////////////////
  77.  
  78. unsigned char Get_Scan_Code(void)
  79. {
  80. // use BIOS functions to retrieve the scan code of the last pressed key
  81. // if a key was pressed at all, otherwise return 0
  82.  
  83. int return_key;
  84.  
  85. #pragma aux bios_scan_code = \
  86.    "mov ah,01h"  \    
  87.    "int 16h"     \
  88.    "jz buffer_empty" \
  89.    "mov ah,00h"      \
  90.    "int 16h"         \
  91.    "mov al,ah"       \
  92.    "xor ah,ah"      \
  93.    "jmp done"        \
  94. "buffer_empty: xor ax,ax"     \
  95. "done:"               \
  96.     value [ax]      \
  97.     modify [ax];
  98. /*_asm
  99.    {
  100.    mov ah,01h      ; function #1 which is "key ready"
  101.    int 16h         ; call the BIOS keyboard interrupt
  102.    jz buffer_empty ; if there was no key ready then exit
  103.    mov ah,00h      ; function #0: retrieve raw scan code
  104.    int 16h         ; call the BIOS keyboard interrupt
  105.    mov al,ah       ; result is placed by BIOS in ah, copy it to al
  106.    xor ah,ah       ; zero out ah
  107.    jmp done        ; jump to end so ax doesn't get reset
  108.  
  109. buffer_empty:
  110.      xor ax,ax     ; a key was retrieved so write a 0 into ax to reflect this
  111. done:
  112.     } // end asm
  113. */
  114. return_key = bios_scan_code();
  115.  
  116. return return_key;
  117.  
  118. // 8 or 16 bit data is returned in AX, hence no need to explicitly say return()
  119.  
  120. } // end Get_Scan_Code
  121.  
  122. //////////////////////////////////////////////////////////////////////////////
  123.  
  124. void _interrupt _far Keyboard_Driver()
  125. {
  126. // this function is used as the new keyboard driver. once it is installed
  127. // it will continually update a keyboard state table that has an entry for
  128. // every key on the keyboard, when a key is down the appropriate entry will be
  129. // set to 1, when released the entry will be reset. any key can be querried by
  130. // accessing the keyboard_state[] table with the make code of the key as the
  131. // index
  132.  
  133. // need to use assembly for speed since this is an interrupt
  134.  
  135.  #pragma aux get_raw_key = \
  136.              "sti" \ 
  137.              "in al, 60h"  \
  138.              "xor ah,ah"         \
  139.              "mov raw_scan_code, ax"      \
  140.              "in al, 61h"       \
  141.              "or al, 82h"        \ 
  142.              "out 61h, al"  \
  143.              "and al,7fh"        \
  144.              "out 61h, al"    \
  145.              "mov al,20h"\
  146.              "out 20h, al"  \
  147.              modify  [ax];
  148.                                                   // when this baby hits 88 mph, your gonna see
  149.                                                   // some serious @#@#$%
  150. /* _asm
  151.    {
  152.    sti                    ; re-enable interrupts
  153.    in al, KEY_BUFFER      ; get the key that was pressed from the keyboard
  154.    xor ah,ah              ; zero out upper 8 bits of AX
  155.    mov raw_key, ax        ; store the key in global variable
  156.    in al, KEY_CONTROL     ; set the control register to reflect key was read
  157.    or al, 82h             ; set the proper bits to reset the keyboard flip flop
  158.    out KEY_CONTROL,al     ; send the new data back to the control register
  159.    and al,7fh
  160.    out KEY_CONTROL,al     ; complete the reset
  161.    mov al,20h             ; reset command
  162.    out PIC_PORT,al        ; tell PIC to re-enable interrupts
  163.  
  164.    } // end inline assembly
  165. */
  166. // update the keyboard table
  167.  
  168. // test if the scan code was a make code or a break code
  169.  
  170. get_raw_key();
  171.  
  172. if ((raw_scan_code) <128)
  173.    {
  174.    // index into table and set this key to the "on" state if it already isn't
  175.    // on
  176.  
  177.    if (keyboard_state[raw_scan_code]==KEY_UP)
  178.       {
  179.       // there is one more active key
  180.  
  181.       keys_active++;
  182.  
  183.       // update the state table
  184.  
  185.       keyboard_state[raw_scan_code] = KEY_DOWN;
  186.  
  187.       } // end if key wasn't already pressed
  188.  
  189.    } // end if a make code
  190. else
  191.    {
  192.    // must be a break code, therefore turn the key "off"
  193.    // note that 128 must be subtracted from the raw key to access the correct
  194.    // element of the state table
  195.  
  196.    if (keyboard_state[raw_scan_code-128]==KEY_DOWN)
  197.       {
  198.       // there is one less active key
  199.  
  200.       keys_active--;
  201.  
  202.       // update the state table
  203.  
  204.       keyboard_state[raw_scan_code-128] = KEY_UP;
  205.  
  206.       } // end if key wasn't already pressed
  207.  
  208.    } // end else
  209.  
  210. } // end Keyboard_Driver
  211.  
  212. ///////////////////////////////////////////////////////////////////////////////
  213.  
  214. void Keyboard_Install_Driver(void)
  215. {
  216. // this function installs the new keyboard driver
  217.  
  218. int index; // used as loop variable
  219.  
  220. // clear out the keyboard state table
  221.  
  222. for (index=0; index<128; index++)
  223.     keyboard_state[index]=0;
  224.  
  225. // save the old keyboard driver
  226.  
  227. Old_Keyboard_ISR = _dos_getvect(KEYBOARD_INTERRUPT);
  228.  
  229. // install the new keyboard driver
  230.  
  231. _dos_setvect(KEYBOARD_INTERRUPT, Keyboard_Driver);
  232.  
  233. } // end Keyboard_Install_Driver
  234.  
  235. ///////////////////////////////////////////////////////////////////////////////
  236.  
  237. void Keyboard_Remove_Driver(void)
  238. {
  239.  
  240. // this functions restores the old keyboard driver (DOS version) with the
  241. // previously saved vector
  242.  
  243. _dos_setvect(KEYBOARD_INTERRUPT, Old_Keyboard_ISR);
  244.  
  245. } // end Keyboard_Remove_Driver
  246.  
  247. //////////////////////////////////////////////////////////////////////////////
  248. ////////////////////// C O M M E N T E D  I N P U T  C O D E     /////////////
  249. //////////////////////////////////////////////////////////////////////////////
  250.  
  251. /*
  252. unsigned char Joystick_Buttons(unsigned char button)
  253. {
  254.  
  255. // this function reads the state of the joystick buttons by retrieving the
  256. // appropriate bit in the joystick port
  257.  
  258. outp(JOYPORT,0); // clear the joystick port and request a sample
  259.  
  260. // invert buttons then mask with request so that a button that is pressed
  261. // returns a "1" instead of a "0"
  262.  
  263. return( (unsigned char)(~inp(JOYPORT) & button));
  264.  
  265. } // end Joystick_Buttons
  266.  
  267. //////////////////////////////////////////////////////////////////////////////
  268.  
  269. unsigned int Joystick(unsigned char stick)
  270. {
  271. // this function will read a joystick by starting the timing circuits connected
  272. // to each joystick pot, when the timing circuit has charged the joystick
  273. // bit will revert to 0, the time this process takes is proportional to
  274. // the joystick position and is returned as the result
  275.  
  276.  _asm
  277.     {
  278.     cli                    ; disable interupts for timing purposes
  279.  
  280.     mov ah, byte ptr stick ; select joystick to read with bitmask
  281.     xor al,al              ; zero out al
  282.     xor cx,cx              ; clear cx i.e. set it to 0
  283.     mov dx,JOYPORT         ; point dx to the joystick port
  284.     out dx,al              ; start the 555 timers charging
  285. charged:
  286.     in al,dx               ; read the joystick port and test of the bit
  287.     test al,ah             ; has reverted back to 0
  288.     loopne charged         ; if the joystick circuit isn't charged then
  289.                            ; decrement cx and loop
  290.  
  291.  
  292.     xor ax,ax              ; zero out ax
  293.     sub ax,cx              ; subtract cx from ax to get a number that increases
  294.                            ; as the joystick position in moved away from neutral
  295.  
  296.     sti                    ; re-enable interrupts
  297.  
  298.     } // end asm
  299.  
  300. // ax has the 16 result, so no need for an explicit return
  301.  
  302. } // end Joystick
  303.  
  304. //////////////////////////////////////////////////////////////////////////////
  305.  
  306. unsigned int Joystick_Bios(unsigned char stick)
  307. {
  308. // read the joystick using bios interrupt 15h with the joystick function 84h
  309.  
  310. union _REGS inregs, outregs; // used to hold CPU registers
  311.  
  312. inregs.h.ah = 0x84; // joystick function 84h
  313. inregs.x.dx = 0x01; // read joysticks subfunction 1h
  314.  
  315. // call the BIOS joystick interrupt
  316.  
  317. _int86(0x15,&inregs, &outregs);
  318.  
  319. // return requested joystick
  320.  
  321. switch(stick)
  322.       {
  323.       case JOYSTICK_1_X:  // ax has joystick 1's X axis
  324.            {
  325.            return(outregs.x.ax);
  326.            } break;
  327.  
  328.       case JOYSTICK_1_Y:  // bx has joystick 1's Y axis
  329.            {
  330.            return(outregs.x.bx);
  331.            } break;
  332.  
  333.       case JOYSTICK_2_X:  // cx has joystick 2's X axis
  334.            {
  335.            return(outregs.x.cx);
  336.            } break;
  337.  
  338.       case JOYSTICK_2_Y:  // dx has joystick 2's Y axis
  339.            {
  340.            return(outregs.x.dx);
  341.            } break;
  342.  
  343.       default:break;
  344.  
  345.       } // end switch stick
  346.  
  347. } // end Joystick_Bios
  348.  
  349. //////////////////////////////////////////////////////////////////////////////
  350.  
  351. void Joystick_Calibrate(int stick,int method)
  352. {
  353.  
  354. // this function is used to calibrate the a joystick. the function will
  355. // query the user to move the joystick in circlular motion and then release
  356. // the stick back to the neutral position and press the fire button. using
  357. // this information the function will compute the max,min and neutral
  358. // values for both the X and Y axis of the joystick. these values will
  359. // then be stored in global variables so they can be used by other
  360. // functions, note the function can use either the BIOS joystick call
  361. // or the low level one we made
  362.  
  363. unsigned int x_value, // used to read values of X and Y axis in real-time
  364.              y_value;
  365.  
  366. // which stick does caller want to calibrate?
  367.  
  368. if (stick==JOYSTICK_1)
  369.    {
  370.    printf("\nCalibrating Joystick #1: Move the joystick in a circle, then");
  371.    printf("\nplace the stick into it's neutral position and press fire.");
  372.  
  373.    // set calibrations values to extremes
  374.  
  375.    joystick_1_max_x = 0;
  376.    joystick_1_max_y = 0;
  377.    joystick_1_min_x = 32000;
  378.    joystick_1_min_y = 32000;
  379.  
  380.    // process X and Y values in real time
  381.  
  382.    while(!Joystick_Buttons(JOYSTICK_BUTTON_1_1 | JOYSTICK_BUTTON_1_2))
  383.         {
  384.         // get the new values and try to update calibration
  385.  
  386.         // test if user wants to use bios or low level
  387.  
  388.         if (method==USE_BIOS)
  389.            {
  390.            x_value = Joystick_Bios(JOYSTICK_1_X);
  391.            y_value = Joystick_Bios(JOYSTICK_1_Y);
  392.            }
  393.         else
  394.            {
  395.            x_value = Joystick(JOYSTICK_1_X);
  396.            y_value = Joystick(JOYSTICK_1_Y);
  397.            }
  398.         // update globals with new extremes
  399.  
  400.         // process X - axis
  401.  
  402.         if (x_value >= joystick_1_max_x)
  403.             joystick_1_max_x = x_value;
  404.  
  405.         if (x_value <= joystick_1_min_x)
  406.             joystick_1_min_x = x_value;
  407.  
  408.         // process Y - axis
  409.  
  410.         if (y_value >= joystick_1_max_y)
  411.             joystick_1_max_y = y_value;
  412.  
  413.         if (y_value <= joystick_1_min_y)
  414.             joystick_1_min_y = y_value;
  415.  
  416.         } // end while
  417.  
  418.         // stick is now in neutral position so record the values here also
  419.  
  420.         joystick_1_neutral_x = x_value;
  421.         joystick_1_neutral_y = y_value;
  422.  
  423.    // notify user process is done
  424.  
  425.    printf("\nJoystick #1 Calibrated. Press the fire button to exit.");
  426.  
  427.    while(Joystick_Buttons(JOYSTICK_BUTTON_1_1 | JOYSTICK_BUTTON_1_2));
  428.    while(!Joystick_Buttons(JOYSTICK_BUTTON_1_1 | JOYSTICK_BUTTON_1_2));
  429.  
  430.    } // end calibrate joystick #1
  431.  
  432. else
  433. if (stick==JOYSTICK_2)
  434.    {
  435.    printf("\nCalibrating Joystick #1: Move the joystick in a circle, then");
  436.    printf("\nplace the stick into it's neutral position and press fire.");
  437.  
  438.    // set calibrations values to extremes
  439.  
  440.    joystick_2_max_x = 0;
  441.    joystick_2_max_y = 0;
  442.    joystick_2_min_x = 32000;
  443.    joystick_2_min_y = 32000;
  444.  
  445.    // process X and Y axis values in real time
  446.  
  447.    while(!Joystick_Buttons(JOYSTICK_BUTTON_2_1 | JOYSTICK_BUTTON_2_2))
  448.         {
  449.         // get the new values and try to update calibration
  450.  
  451.         // test if user wants to use bios or low level
  452.  
  453.         if (method==USE_BIOS)
  454.            {
  455.            x_value = Joystick_Bios(JOYSTICK_1_X);
  456.            y_value = Joystick_Bios(JOYSTICK_1_Y);
  457.            }
  458.         else
  459.            {
  460.            x_value = Joystick(JOYSTICK_1_X);
  461.            y_value = Joystick(JOYSTICK_1_Y);
  462.            }
  463.  
  464.         // update globals with new extremes
  465.  
  466.         // process X - axis
  467.  
  468.         if (x_value >= joystick_2_max_x)
  469.             joystick_2_max_x = x_value;
  470.         else
  471.         if (x_value <= joystick_2_min_x)
  472.             joystick_2_min_x = x_value;
  473.  
  474.         // process Y - axis
  475.  
  476.         if (y_value >= joystick_2_max_y)
  477.             joystick_2_max_y = y_value;
  478.         else
  479.         if (y_value <= joystick_2_min_y)
  480.             joystick_2_min_y = y_value;
  481.  
  482.         } // end while
  483.  
  484.         // stick is now in neutral position so record the values here also
  485.  
  486.         joystick_2_neutral_x = x_value;
  487.         joystick_2_neutral_y = y_value;
  488.  
  489.    // notify user process is done
  490.  
  491.    printf("\nJoystick #2 Calibrated. Press the fire button to exit.");
  492.  
  493.    while(Joystick_Buttons(JOYSTICK_BUTTON_1_1 | JOYSTICK_BUTTON_1_2));
  494.    while(!Joystick_Buttons(JOYSTICK_BUTTON_1_1 | JOYSTICK_BUTTON_1_2));
  495.  
  496.    } // end calibrate joystick #2
  497.  
  498. } // end Joystick_Calibrate
  499.  
  500. //////////////////////////////////////////////////////////////////////////////
  501.  
  502. int Joystick_Available(int stick_num)
  503. {
  504. // test if the joystick is plugged in that the user is requesting tested
  505. // note the use of the BIOS joystick function, it is very reliable
  506.  
  507. if (stick_num == JOYSTICK_1)
  508.    {
  509.    // test if joystick 1 is plugged in by testing the port values
  510.    // they will be 0,0 if there is no stick
  511.  
  512.    return(Joystick_Bios(JOYSTICK_1_X)+Joystick_Bios(JOYSTICK_1_Y));
  513.  
  514.    } // end if joystick 1
  515. else
  516.    {
  517.    // test if joystick 2 is plugged in by testing the port values
  518.    // they will be 0,0 if there is no stick
  519.  
  520.    return(Joystick_Bios(JOYSTICK_2_X)+Joystick_Bios(JOYSTICK_2_Y));
  521.  
  522.    } // end else joystick 2
  523.  
  524. } // end Joystick_Available
  525.  
  526. ///////////////////////////////////////////////////////////////////////////////
  527.  
  528. int Mouse_Control(int command, int *x, int *y,int *buttons)
  529. {
  530. union _REGS inregs,  // CPU register unions to be used by interrupts
  531.             outregs;
  532.  
  533. // what is caller asking function to do?
  534.  
  535. switch(command)
  536.       {
  537.  
  538.       case MOUSE_RESET: // this resets the mouse
  539.            {
  540.  
  541.            // mouse subfunction 0: reset
  542.  
  543.            inregs.x.ax = 0x00;
  544.  
  545.            // call the mouse interrupt
  546.  
  547.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  548.  
  549.            // return number of buttons on this mouse
  550.  
  551.            *buttons = outregs.x.bx;
  552.  
  553.            // return success/failure of function
  554.  
  555.            return(outregs.x.ax);
  556.  
  557.            } break;
  558.  
  559.       case MOUSE_SHOW: // this shows the mouse
  560.            {
  561.            // this function increments the internal mouse visibility counter.
  562.            // when it is equal to 0 then the mouse will be displayed.
  563.  
  564.            // mouse subfunction 1: increment show flag
  565.  
  566.            inregs.x.ax = 0x01;
  567.  
  568.            // call the mouse interrupt
  569.  
  570.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  571.  
  572.            // return success always
  573.  
  574.            return(1);
  575.  
  576.            } break;
  577.  
  578.       case MOUSE_HIDE:  // this hides the mouse
  579.            {
  580.            // this function decrements the internal mouse visibility counter.
  581.            // when it is equal to -1 then the mouse will be hidden.
  582.  
  583.            // mouse subfunction 2: decrement show flag
  584.  
  585.            inregs.x.ax = 0x02;
  586.  
  587.            // call the interrupt
  588.  
  589.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  590.  
  591.            // return success
  592.  
  593.            return(1);
  594.  
  595.            } break;
  596.  
  597.       case MOUSE_POSITION_BUTTONS: // this gets both the position and
  598.                                    // state of buttons
  599.            {
  600.            // this functions computes the absolute position of the mouse
  601.            // and the state of the mouse buttons
  602.  
  603.            // mouse subfunction 3: get position and buttons
  604.  
  605.            inregs.x.ax = 0x03;
  606.  
  607.            // call the mouse interrupt
  608.  
  609.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  610.  
  611.            // extract the info and send back to caller via pointers
  612.  
  613.            *x       = outregs.x.cx;
  614.            *y       = outregs.x.dx;
  615.            *buttons = outregs.x.bx;
  616.  
  617.            // return success always
  618.  
  619.            return(1);
  620.  
  621.            } break;
  622.  
  623.       case MOUSE_MOTION_REL:  // this gets the relative motion of mouse
  624.            {
  625.  
  626.            // this functions gets the relative mouse motions from the last
  627.            // call, these values will range from -32768 to +32767 and
  628.            // be in mickeys which are 1/200 of inch or 1/400 of inch
  629.            // depending on the resolution of your mouse
  630.  
  631.            // subfunction 11: get relative motion
  632.  
  633.            inregs.x.ax = 0x0B;
  634.  
  635.            // call the interrupt
  636.  
  637.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  638.  
  639.            // extract the info and send back to caller via pointers
  640.  
  641.            *x       = outregs.x.cx;
  642.            *y       = outregs.x.dx;
  643.  
  644.            // return success
  645.  
  646.            return(1);
  647.  
  648.            } break;
  649.  
  650.       case MOUSE_SET_SENSITIVITY:
  651.            {
  652.            // subfunction 26: set sensitivity
  653.  
  654.            inregs.x.ax = 0x1A;
  655.  
  656.            // place the desired sensitivity and double speed values in place
  657.  
  658.            inregs.x.bx = *x;
  659.            inregs.x.cx = *y;
  660.            inregs.x.dx = *buttons;
  661.  
  662.            // call the interrupt
  663.  
  664.            _int86(MOUSE_INTERRUPT, &inregs, &outregs);
  665.  
  666.            // always return success
  667.  
  668.            return(1);
  669.  
  670.            } break;
  671.  
  672.       default:break;
  673.  
  674.       } // end switch
  675.  
  676. } // end Mouse_Control
  677.  
  678. */
  679.  
  680.  
  681.  
  682.