home *** CD-ROM | disk | FTP | other *** search
- /* joystklo.c Low level game-adapter port access functions.
-
- The functions in this module
- 1. detect the presence of a game adapter
- 2. verify which axes are functional
- 3. read current button status
- 4. read changed button status
- 5. read current joystick resistance position
- 6. allow change of active axes within this system
- as long as they have been found functional.
-
- See file joystklo.se for pseudo code/structured english
- and joystick.doc for an explanation of the functions.
-
- This module was written for Borland C++ 2.0.
- No C++ extensions were used, this is all C and Assembler.
-
- I've done limited testing on an old XT with 11/08/82 BIOS
- and on my PS/2 like 386 AT and haven't found anything yet...
-
- If you find this module useful, great!!!
-
- This module has been released to the public domain
- Tue 01-07-1992 23:30:18
- by Ed Torgerson : CIS 70313,456, GEnie E.TORGERSON1.
- any constructive correspondence is welcome.
-
- Thanks to Gary Blaine, for putting out JOY.ARC for all to use.
-
- -----------------------------------------------------------------------------*/
-
- #include <dos.h>
- #pragma inline
-
- /*-- Global defines -----*/
- #define NOP 0x90 /* define NOP instruction for __emit__ delay */
- #define TIME_OUT 1000 /* one-shot time out value for reading position */
- /* N.B. Interrupts are disabled during timing */
- /* N.B. My loops are faster than Gary Blaine's, */
- /* the TIME_OUT value is proportionally higher. */
-
- /*-- Global variables -----*/
- unsigned char G_Stick_Active_Axes ; /* bit mask of currently active axes */
- unsigned char G_Stick_Valid_Axes ; /* bit mask of valid axes */
- unsigned char G_LastCallState = 0xF0 ; /* bit image of last button state */
-
- /*-- Function Prototypes -----*/
- int JstGetChangedButton( void ) ; /* get changed button status */
- int JstGetButton( void ) ; /* get present button status */
- int JstGetPosition(int axis_mask) ; /* get position on given axis */
- int JstDetect ( void ) ; /* detect active game port lines */
- int JstGetValidAxes ( void ) ; /* return mask of valid axes */
- int JstGetActiveAxes( void ) ; /* return mask of active axes */
- int JstSetActiveAxes( unsigned mask) ; /* set mask of active axes */
-
- /*-- Function Definitions ---------------------------------------------------*/
- int JstGetValidAxes ( void ) /* return bit mask of valid axes */
- {
- return ( (unsigned) G_Stick_Valid_Axes ) ;
- }
- /*---------------------------------------------------------------------------*/
- int JstGetActiveAxes( void ) /* return bit mask of active axes */
- {
- return ( (unsigned) G_Stick_Active_Axes ) ;
- }
- /*---------------------------------------------------------------------------*/
- int JstSetActiveAxes( unsigned mask ) /* set bit mask of active axes */
- {
- asm {
- mov ax, mask ; /* get axis mask to set */
- and al, G_Stick_Valid_Axes ; /* set check value */
- cmp al, mask ; /* compare mask to check value */
- je ValidUserAxis ; /* valid if equal */
- }
- return ( 0 ) ; /* invalid mask */
- ValidUserAxis:
- G_Stick_Active_Axes = (unsigned char) mask ;
- return ( 1 ) ; /* success */
- }
- /*---------------------------------------------------------------------------*/
- int JstDetect ( ) /* detect active game port lines */
- {
- register unsigned char x, y ;
-
- outportb ( 0x201, 0 ) ; /* initialize game adapter one-shot timers */
- delay (200) ; /* give the timers a chance to clear */
- x = inportb ( 0x201 ) ; /* get initial game adapter position flags */
- x = x & 0xf ; /* lose upper nibble */
- outportb ( 0x201, 0 ) ; /* initialize game adapter one-shot timers */
- __emit__(NOP);
- __emit__(NOP);
- __emit__(NOP);
- __emit__(NOP);
- __emit__(NOP);
- y = inportb ( 0x201 ) ; /* get initial game adapter position flags */
- y = y & 0xf ; /* lose upper nibble */
- x = x ^ y ; /* any axes that change are functional */
- G_Stick_Active_Axes = x ; /* set currently active axes */
- G_Stick_Valid_Axes = x ; /* set valid axes mask */
- return ( (unsigned) x ) ;
- } /*-- end JstDetect */
-
- /*---------------------------------------------------------------------------*/
- int JstGetButton() /* get present button status */
- {
- asm {
- mov dx, 201h ; /* port address of game adapter */
- in al, dx ; /* al = game port state */
- and al, 0xF0 ; /* lose lower nibble */
- mov G_LastCallState, al ; /* save button state for next call */
- xor al, 0xF0 ; /* flip bits */
- mov dh, al ; /* dl = button down mask */
- xor al, 0xF0 ; /* al = button up mask */
- mov cl, 4
- shr al, cl ; /* shift mask to lower nibble */
- or al, dh ; /* al = combined button event mask */
- xor ah, ah ; /* zero out ah for return */
- }
- return (_AX) ;
- } /*-- end JstGetButton */
- /*---------------------------------------------------------------------------*/
- int JstGetChangedButton( ) /* get changed button status */
- {
- asm {
- mov dx, 201h ; /* port address of game adapter */
- in al, dx ; /* al = game port state */
- and al, 0xF0 ; /* lose lower nibble */
- mov dh, al ; /* dl = current button state */
- xor al, G_LastCallState ; /* al = changed button mask */
- jnz ButtonChanged
- }
- return (0) ;
- ButtonChanged:
- asm {
- mov dl, G_LastCallState ; /* dl = last call state */
- mov G_LastCallState, dh ; /* save button state for next call */
- and dl, al ; /* dl = button down mask */
- xor al, dl ; /* al = button up mask */
- mov cl, 4
- shr al, cl ; /* shift mask to lower nibble */
-
- or al, dl ; /* al = combined button event mask */
- xor ah, ah ; /* zero out ah for return */
- }
- return (_AX) ;
- } /*-- end JstGetChangedButton */
- /*---------------------------------------------------------------------------*/
- int JstGetPosition(int axis_mask ) /* get position on given axis */
- {
- asm {
- mov al, G_Stick_Active_Axes ; /* get currently active axes */
- test al, axis_mask ; /* check if given axis is active */
- jnz ValidAxis ; /* go on if valid */
- }
- return (0) ; /* error - invalid parameter given */
- ValidAxis:
- asm {
- cli ; /* disable interrupts for accurate timing */
- mov dx, 0x43 ; /* 8253 write command port */
- xor al, al ; /* 8253 latch timer 0 command */
- out dx,al
- nop ; /* delay so latch regs can be filled */
- nop
- nop
- nop
- nop
- mov dx, 0x40 ; /* 8253 read port */
- in al, dx ; /* read low byte of 8253 timer count */
- mov cl, al ; /* copy to CL */
- nop ; /* delay so latch regs can be filled */
- nop
- nop
- mov dx, 0x40 ; /* 8253 read port */
- in al, dx ; /* read high byte of 8253 timer count */
- mov ch, al ; /* !!!! CX = start_time !!!!*/
- push cx ; /* just to be safe */
-
- ;----- /* Time to start timin' */
- mov dx, 0x201 ; /* write to game adapter */
- mov al, 0 ; /* initialize one-shot timers */
- out dx, al ;
-
- xor si, si ; /* set up timing loop */
- mov bx, axis_mask ; /* get axis mask for quick read */
- }
- DoLoop1:
- asm {
- mov dx, 0x201 ; /* read game adapter */
- in al, dx ;
- test al, bl ; /* test for matching bit */
- jz short DoneLoop1 ; /* go on if match */
- inc si ;
- cmp si, TIME_OUT ; /* quit if timed out */
- jz short Quit0 ;
- jmp short DoLoop1 ; /* loop back */
- }
- Quit0:
- asm {
- sti ; /* re-enable interrupts */
- }
- return (0) ; ; /* error - loop timed out */
- DoneLoop1:
- asm {
- mov dx, 0x43 ; /* 8253 write command port */
- xor al, al ; /* 8253 latch timer 0 command */
- out dx,al
- nop ; /* delay so latch regs can be filled */
- nop
- nop
- nop
- nop
- mov dx, 0x40 ; /* 8253 read port */
- in al, dx ; /* read low byte of 8253 timer count */
- mov bl, al ; /* copy to BL */
- nop ; /* delay so latch regs can be filled */
- nop
- nop
- mov dx, 0x40 ; /* 8253 read port */
- in al, dx ; /* read high byte of 8253 timer count */
- mov bh, al ; /* !!!! BX = finish_time !!!! */
- sti ; /* re-enable interrupts */
- }
- asm {
- pop cx ; /* start time */
- cmp cx, bx ; /* jump if start < finish */
- jb short StartIsLess
- sub cx, bx ; /* result = start - finish; */
- mov ax, cx ; /* !!!! AX = result !!!! */
- jmp short AdjustResult
- }
- StartIsLess:
- asm {
- mov ax, 65535 ; /* result = 0xffff - finish + start */
- sub ax, bx
- add ax, cx ; /* !!!! AX = result !!!! */
- }
- AdjustResult:
- asm {
- and ax, 8176 ; /* result & 0x1ff0 */
- mov cl, 4 ;
- shr ax, cl ; /* result = result >> 4 */
- push ax ; /* save ax */
-
- xor si, si ; /* set up loop to clear rest of bits */
- mov cl, G_Stick_Valid_Axes ; /* get mask of valid axes */
- not cl ; /* flip axis mask for test */
- and cl, 0xf ; /* just to be sure... */
- }
- DoLoop2:
- asm {
- mov dx, 0x201 ; /* read game adapter */
- in al, dx ;
- and al, 0xf ; /* lose upper nibble */
- cmp al, cl ; /* check if all bits have flipped */
- jz DoneLoop2 ; /* jump if we're done */
- inc si ; /* increment counter */
- cmp si, TIME_OUT ; /* quit if timed out */
- jz short DoneLoop2
- jmp short DoLoop2 ; /* loop back */
- }
- DoneLoop2:
- asm {
- pop ax ; /* get back our result */
- }
- return (_AX) ;
- } /* end JstGetPosition */
- /*---------------------------------------------------------------------------*/
-
- /* end joystklo.c */
-