[Back to JOYSTICK SWAG index] [Back to Main SWAG index] [Original]
{
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.
[Back to JOYSTICK SWAG index] [Back to Main SWAG index] [Original]