home *** CD-ROM | disk | FTP | other *** search
- {
- The basic approach to reading a joystick is to monitor port 201h. The eight
- bits at that port correspond to:
-
- 01h - Joystick A, "X" position
- 02h - Joystick A, "Y" position
- 04h - Joystick B, "X" position
- 08h - Joystick B, "Y" position
- 10h - Joystick A, button 1
- 20h - Joystick A, button 2
- 40h - Joystick B, button 1
- 80h - Joystick B, button 2
-
- The buttons are easy: a bit of "0" means "pressed" and "1" means "not
- pressed". But a single bit to read a joystick position?!? Here's what
- you do:
-
- 1) Write a value -- any value -- to port 201h. The four lowest bits
- will then all assume a value of "1".
-
- 2) Start a counter, and see how many iterations it takes for your
- desired bit to go to zero. The number of iterations = the joystick
- position, with lower values corresponding to "left" or "up" and
- higher values corresponding to "right" or "down".
-
- Like any joystick code, thess routines return the button statuses and the
- joystick positions. They also return boolean indicators of whether the
- stick is left or right, up or down, based on a sensitivity you define.
-
- The routines you call are:
-
- procedure calibrate(r: real) -- Call this at the beginning of your program.
- Determines presence of joysticks and how
- far the stick has to be moved to constitute
- L/R/U/D. "r" is a real value from 0 to 1;
- a value of 0.25 means that the stick has to
- move 25% from center to count as L/R/U/D.
- procedure readsticks -- Reads sticks and buttons. Call this once
- every round of play or whatever.
-
- THE CODE:
- {--------------------------------------------------------------------------}
- unit joystick;
-
- interface
-
- var jax, jay, jbx, jby: word; { Joystick positions }
- ja1, ja2, jaleft, jaright, jaup, jadown, { JA1, JA2, JB1, JB2 = buttons }
- jb1, jb2, jbleft, jbright, jbup, jbdown, { GotJoystickA/B record which }
- gotjoysticka, gotjoystickb: boolean; { joysticks are present }
-
- { lefts, rights, ups, downs are determined when the joysticks are read:
- if the stick is sufficiently off-center, L, R, U, and/or D will be
- flagged appropriately }
-
- procedure readsticks; { reads joysticks }
- procedure calibrate(offcenterthresh: real); { determines what stick values
- constitute L/R/U/D }
- {--------------------------------------------------------------------------}
- implementation
-
- var jal, jar, jau, jad, jbl, jbr, jbu, jbd: word; { thresholds for L/R/U/D }
- {--------------------------------------------------------------------------}
- procedure calibrate(offcenterthresh: real); { get base figures for sticks }
- begin
- gotjoysticka := true; { initially assume both sticks }
- gotjoystickb := true; { are present }
- readsticks; { get stick positions }
- gotjoysticka := (jax > 0) or (jay > 0); { if joystick reads as position }
- gotjoystickb := (jbx > 0) or (jby > 0); { (0,0), it doesn't exist }
- jal := round(jax*(1 - offcenterthresh)); { OFFCENTERTHRESH is a real }
- jar := round(jax*(1 + offcenterthresh)); { from 0 to 1 that tells the }
- jau := round(jay*(1 - offcenterthresh)); { system how far off-center }
- jad := round(jay*(1 + offcenterthresh)); { the stick has to be to get }
- jbl := round(jbx*(1 - offcenterthresh)); { counted as L/R/U/D. For }
- jbr := round(jbx*(1 + offcenterthresh)); { example, a value of "0.25" }
- jbu := round(jby*(1 - offcenterthresh)); { means the stick has to be }
- jbd := round(jby*(1 + offcenterthresh)); { 25% below base to be L / U, }
- end; { or 25% above to be R / D. }
-
- procedure readsticks; { Reads sticks & buttons. }
- var gotax, gotay, gotbx, gotby: boolean; { whether we have a stick value }
- cnter: word; { just a counter }
- begin
- if gotjoysticka or gotjoystickb then begin { if no sticks, skip reading them }
- ja1 := (port[$201] and $10) = 0; { read the buttons }
- ja2 := (port[$201] and $20) = 0;
- jb1 := (port[$201] and $40) = 0;
- jb2 := (port[$201] and $80) = 0;
- gotax := not gotjoysticka; { Flags: do we have values yet? }
- gotay := not gotjoysticka; { Set to "true" for nonexistent }
- gotbx := not gotjoystickb; { stick -- no need to give }
- gotby := not gotjoystickb; { them a second thought }
- jax := 0; { set actual stick positions to }
- jay := 0; { zero -- on "existing" sticks }
- jbx := 0; { the number will increase }
- jby := 0;
- asm
- mov cx, 0000h { set counter to zero }
- mov al, 0fh { AL contains "new" port value (initialized to 0fh) }
- mov ah, al { AH contains "old" port value (initialized to 0fh) }
- mov dx, 0201h { load up joystick port }
- out dx, al { "prime" joystick port by writing 0fh to it }
- @beginloop: { the stick-reading loop }
-
- in al, dx { read joystick port }
- and al, 0fh { "and" it with 0fh to "eliminate" the button bits }
- cmp al, ah { compare to the "old" port value }
- je @endloop { if no change, skip past position checking }
-
- @chkax: { checking "X" value on joystick "A" }
- cmp gotax, 01h { see if "gotax" equals 1: if so, we've already got }
- je @chkay { a reading on it, and skip to "ay" readings }
- test al, 01h { if first bit of BL is a 1: if so, we don't have a }
- jnz @chkay { value for "ax", so jump over to "ay" }
- mov gotax, 01h { set boolean "gotax" to "true" }
- mov jax, cx { record counter value }
-
- @chkay: { checking "Y" value on joystick "A" }
- cmp gotay, 01h
- je @chkbx
- test al, 02h
- jnz @chkbx
- mov gotay, 01h
- mov jay, cx
-
- @chkbx: { checking "X" value on joystick "B" }
- cmp gotbx, 01h
- je @chkby
- test al, 04h
- jnz @chkby
- mov gotbx, 01h
- mov jbx, cx
-
- @chkby: { checking "Y" value on joystick "B" }
- cmp gotby, 01h
- je @endloop
- test al, 08h
- jnz @endloop
- mov gotby, 01h
- mov jby, cx
-
- @endloop: { counter increments and data-evaluating }
- mov ah, al { store "new" port value as "old" value for next pass }
- inc cx { increment counter }
- cmp cx, 65535 { compare counter to 65535 }
- je @ending { if counter = 65535, get out of loop }
- cmp gotax, 01h { see if we have a value for "ax"; }
- jne @beginloop { if not, jump to top of loop for another pass }
- cmp gotay, 01h { check "ay" }
- jne @beginloop
- cmp gotbx, 01h { check "bx" }
- jne @beginloop
- cmp gotby, 01h { check "by" }
- jne @beginloop
- @ending: { we're past the end of the loop }
- mov cnter,cx { store counter value into "Pascal" variable }
- end;
- end;
- jaleft := (jax < jal); jaright := (jax > jar); { determine L/R/U/D }
- jaup := (jay < jau); jadown := (jay > jad);
- jbleft := (jbx < jbl); jbright := (jbx > jbr);
- jbup := (jby < jbu); jbdown := (jby > jbd);
- end;
- {--------------------------------------------------------------------------}
- end.