home *** CD-ROM | disk | FTP | other *** search
- ;======================================================================
- ;
- ; S T I C K - Assembly language joystick input for Turbo Pascal
- ;
- ;======================================================================
- ;
- ; by Jeff Duntemann 12 February 1988
- ; with thanks to Ted Mirecki for additional insights
- ;
- ; From: COMPLETE TURBO PASCAL 5.0 by Jeff Duntemann
- ; Scott, Foresman & Co., Inc. 1988 ISBN 0-673-38355-5
- ;
- ; STICK is written to be called from Turbo Pascal V4.0 using the
- ; {$L}/EXTERNAL procedure convention.
- ;
- ; Declare the procedure itself as an external using this declaration:
- ;
- ; {$L STICK}
- ; PROCEDURE STICK(StickNumber : Integer VAR X,Y : Integer);
- ; EXTERNAL;
- ;
- ; StickNumber specifies which joystick to read from, and the X and Y
- ; parameters return integers proportional to the joystick's position
- ; at the moment the stick is sampled. These integers will vary from
- ; stick to stick depending on the resistance of the potentiometers
- ; used within the stick, but will typically from from 3 to 150.
- ;
- ; The IBM standard game controller board consists of two pairs of
- ; one-shots, which output a pulse when triggered by an I/O write to
- ; I/O port $201. The length of this pulse is determined by an RC
- ; time constant circuit the resistance portion of which is the
- ; potentiometer in the joystick. As the handle is moved around, the
- ; two potentiometers (one for X, one for Y) run up and back, changing
- ; resistance as they go.
- ;
- ; To read one of the two joysticks, a dummy value (which may be anything
- ; at all) is written to I/O port $201. Port $201 must then be polled
- ; continuously, incrementing a register at each polling event. When
- ; the bit corresponding to that stick's X or Y coordinate changes state,
- ; the count in the register is returned as that coordinate value at the
- ; time the stick was sampled.
- ;
- ; Here is a map of the joystick bits as returned by port $201:
- ;
- ; |7 6 5 4 3 2 1 0|
- ; | | | |
- ; | | | - - - - - - -> X coordinate, joystick #1
- ; | | - - - - - - - -> Y coordinate, joystick #1
- ; | - - - - - - - - -> X coordinate, joystick #2
- ; - - - - - - - - - -> Y coordinate, joystick #2
- ;
- ; One thing to keep in mind is that a bit goes LOW when sampled, and
- ; you must test for a HIGH on that bit to indicate that the one-shot has
- ; timed out.
- ;
- ;
- ; To reassemble/relink STICK:
- ;-------------------------------------
- ; Assemble this file with MASM. "C>MASM STICK;"
- ;
- ;
- ; This structure defines the layout of parameters on the stack.
- ;
- ONSTACK STRUC
- OLDBP DW ? ;TOP OF STACK
- RETADDR DD ? ;FAR RETURN ADDRESS
- YADDR DD ? ;FAR ADDRESS OF X VALUE
- XADDR DD ? ;FAR ADDRESS OF Y VALUE
- STIK_NO DW ? ;STICK NUMBER
- ONSTACK ENDS
-
- CODE SEGMENT PUBLIC
- ASSUME CS:CODE
- PUBLIC STICK
-
- ; EQUATES FOR ONE-SHOT BITS FOR STICKS 1 & 2
-
- STICK_X EQU 1
- STICK_Y EQU 2
-
-
- STICK PROC FAR
- PUSH BP ;SAVE CALLER'S BP
- MOV BP,SP ;STACK POINTER BECOMES NEW BP
- PUSH DS
-
- ; GET THE X AXIS VALUE FIRST
-
- MOV AH,STICK_X ; MOVE IN THE X TEST BIT
- CMP [BP].STIK_NO,2 ; SEE IF WE'RE TESTING STICK #1 OR #2
- JNE TEST_X
- SHL AH,1 ; SHIFT BIT NUMBERS 2 LEFT FOR STICK #2
- SHL AH,1
- TEST_X: MOV AL,1 ; INITIALIZE OUTPUT VALUE
- MOV DX,201H ; SET PORT ADDRESS
- MOV BX,0 ; AND KEEPING THE RUNUP COUNT IN BX
- MOV CX,BX ; LOOP 64K TIMES MAX
- OUT DX,AL ; TRIGGER THE ONE-SHOTS
- AGAIN_X: IN AL,DX ; READ THE ONE-SHOT BITS
- TEST AL,AH ; TEST FOR A HIGH BIT 0
- JE DELAY ; WE'RE DONE IF BIT 0 IS HIGH
- INC BX ; OTHERWISE INCREMENT BX AND LOOP AGAIN
- LOOP AGAIN_X
- MOV BX,-1 ; SET X=-1 IF NO RESPONSE
-
- ; DELAY HERE TO LET THE OTHER THREE PULSES MAX OUT
-
- DELAY: MOV CX,512
- WAIT: LOOP WAIT
-
- ; NOW WE GET THE Y AXIS VALUE
-
- MOV AH,STICK_Y ; MOVE IN THE Y TEST BIT
- CMP [BP].STIK_NO,2 ; SEE IF WE'RE TESTING STICK #1 OR #2
- JNE TEST_Y
- SHL AH,1 ; SHIFT BIT NUMBERS 2 LEFT FOR STICK #2
- SHL AH,1
-
- TEST_Y: MOV SI,0 ; KEEP THE RUNUP COUNT FOR Y IN SI
- MOV CX,SI ; SET LOOP LIMIT TO 64K
- OUT DX,AL ; FIRE THE ONE-SHOTS AGAIN
- AGAIN_Y: IN AL,DX ; READ THE ONE-SHOT BITS
- TEST AL,AH ; TEST FOR A HIGH BIT 1
- JE DONE ; WE'RE DONE IF BIT 1 IS HIGH
- INC SI ; OTHERWISE INCREMENT SI AND LOOP AGAIN
- LOOP AGAIN_Y
- MOV SI,-1 ; SET Y=-1 IF NO RESPONSE
-
- ; MOVE RETURN VALUES FROM REGISTERS INTO VAR PARAMETERS X & Y
-
- DONE: LDS DI,[BP].XADDR ;ADDR OF X INTO DS:DI
- MOV [DI],BX ;X VALUE FROM BX TO DS:DI
- LDS DI,[BP].YADDR ;DITTO FOR Y VALUE FROM SI
- MOV [DI],SI
-
- ; IT'S OVER...NOW CLEAN UP THE STACK AND LEAVE
-
- POP DS
- MOV SP,BP ; CLEAN UP STACK AND LEAVE
- POP BP ; RESTORE CALLER'S BP
-
- RET 10
-
- STICK ENDP
- CODE ENDS
- END