home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SLOWRUNS.ZIP / SLOWSRC.ZIP / MAGIC5.C < prev    next >
C/C++ Source or Header  |  1997-09-11  |  16KB  |  580 lines

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