475 lines
11 KiB
NASM
475 lines
11 KiB
NASM
;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
|
;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
|
;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
|
|
;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
|
|
;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
|
|
;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
|
|
;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
|
|
;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
|
|
;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
|
|
;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|
;
|
|
; $Source: /cvs/cvsroot/d2x/arch/dos/joy2.asm,v $
|
|
; $Revision: 1.3 $
|
|
; $Author: bradleyb $
|
|
; $Date: 2001-10-24 09:25:05 $
|
|
;
|
|
; Contains routines for joystick interface.
|
|
;
|
|
; $Log: not supported by cvs2svn $
|
|
; Revision 1.1.1.1 2001/01/19 03:33:43 bradleyb
|
|
; Import of d2x-0.0.9-pre1
|
|
;
|
|
; Revision 1.1.1.1 1999/06/14 21:57:53 donut
|
|
; Import of d1x 1.37 source.
|
|
;
|
|
; Revision 1.17 1995/10/07 13:22:11 john
|
|
; Added new method of reading joystick that allows higher-priority
|
|
; interrupts to go off.
|
|
;
|
|
; Revision 1.16 1995/03/30 11:03:30 john
|
|
; Made -JoyBios read buttons using BIOS.
|
|
;
|
|
; Revision 1.15 1995/02/14 11:39:36 john
|
|
; Added polled/bios joystick readers..
|
|
;
|
|
; Revision 1.14 1995/01/29 18:36:00 john
|
|
; Made timer count in mode 2 instead of mode 3.
|
|
;
|
|
; Revision 1.13 1994/12/28 15:32:21 john
|
|
; Added code to read joystick axis not all at one time.
|
|
;
|
|
; Revision 1.12 1994/12/27 15:44:59 john
|
|
; Made the joystick timeout be at 1/100th of a second,
|
|
; regardless of CPU speed.
|
|
;
|
|
; Revision 1.11 1994/11/15 12:04:40 john
|
|
; Cleaned up timer code a bit... took out unused functions
|
|
; like timer_get_milliseconds, etc.
|
|
;
|
|
; Revision 1.10 1994/07/01 10:55:54 john
|
|
; Fixed some bugs... added support for 4 axis.
|
|
;
|
|
; Revision 1.9 1994/06/30 20:36:54 john
|
|
; Revamped joystick code.
|
|
;
|
|
; Revision 1.8 1994/04/22 12:52:06 john
|
|
|
|
[BITS 32]
|
|
|
|
[SECTION .data]
|
|
|
|
LastTick dd 0
|
|
TotalTicks dd 0
|
|
|
|
global _joy_bogus_reading
|
|
global _joy_retries
|
|
extern _JOY_PORT
|
|
_joy_bogus_reading dd 0
|
|
_joy_retries dd 0
|
|
RetryCount dd 0
|
|
|
|
|
|
[SECTION .text]
|
|
|
|
; JOY_PORT EQU 0209h
|
|
TDATA EQU 40h
|
|
TCOMMAND EQU 43h
|
|
|
|
joy_get_timer:
|
|
xor al, al ; Latch timer 0 command
|
|
out TCOMMAND, al ; Latch timer
|
|
in al, TDATA ; Read lo byte
|
|
mov ah, al
|
|
in al, TDATA ; Read hi byte
|
|
xchg ah, al
|
|
and eax, 0ffffh
|
|
ret
|
|
|
|
|
|
|
|
|
|
global _joy_read_stick_friendly2
|
|
_joy_read_stick_friendly2:
|
|
push ebx
|
|
push edi
|
|
|
|
mov ebx,[esp+12]
|
|
mov edi,[esp+16]
|
|
mov ecx,[esp+20]
|
|
|
|
; ebx = read mask
|
|
; edi = pointer to event buffer
|
|
; ecx = timeout value
|
|
; returns in eax the number of events
|
|
|
|
mov dword [RetryCount], 0
|
|
mov dword [_joy_bogus_reading], 0
|
|
|
|
_joy_read_stick_friendly_retry:
|
|
inc dword [RetryCount]
|
|
cmp dword [RetryCount], 3
|
|
jbe @@f1
|
|
mov dword [_joy_bogus_reading], 1
|
|
inc dword [_joy_retries]
|
|
mov eax, 0
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
@@f1:
|
|
push ecx
|
|
push ebx
|
|
push edi
|
|
|
|
and ebx, 01111b ; Make sure we only check the right values
|
|
; number of events we found will be in bh, so this also clears it to zero.
|
|
|
|
mov dx, [_JOY_PORT]
|
|
|
|
cli ; disable interrupts while reading time...
|
|
call joy_get_timer ; Returns counter in EAX
|
|
sti ; enable interrupts after reading time...
|
|
mov dword [LastTick], eax
|
|
|
|
waitforstable_f: in al, dx
|
|
and al, bl
|
|
jz ready_f ; Wait for the port in question to be done reading...
|
|
|
|
cli ; disable interrupts while reading time...
|
|
call joy_get_timer ; Returns counter in EAX
|
|
sti ; enable interrupts after reading time...
|
|
xchg eax, dword [LastTick]
|
|
cmp eax, dword [LastTick]
|
|
jb @@f2
|
|
sub eax, dword [LastTick]
|
|
@@f2: ; Higher...
|
|
add dword [TotalTicks], eax
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae ready_f
|
|
jmp waitforstable_f
|
|
|
|
ready_f:
|
|
cli
|
|
mov al, 0ffh
|
|
out dx, al ; Start joystick a readin'
|
|
|
|
call joy_get_timer ; Returns counter in EAX
|
|
mov dword [LastTick], eax
|
|
mov dword [TotalTicks], 0
|
|
|
|
mov [edi], eax ; Store initial count
|
|
add edi, 4
|
|
|
|
again_f: in al, dx ; Read Joystick port
|
|
not al
|
|
and al, bl ; Mask off channels we don't want to read
|
|
jnz flip_f ; See if any of the channels flipped
|
|
|
|
; none flipped -- check any interrupts...
|
|
mov al, 0Ah
|
|
out 20h, al
|
|
in al, 20h ; Get interrupts pending
|
|
cmp al, 0
|
|
je NoInts
|
|
|
|
; Need to do an interrupt
|
|
sti
|
|
nop ; let the interrupt go on...
|
|
cli
|
|
|
|
; See if any axis turned
|
|
in al, dx
|
|
not al
|
|
and al, bl
|
|
jz NoInts
|
|
|
|
; At this point, an interrupt occured, making one or more
|
|
; of the axis values bogus. So, we will restart this process...
|
|
|
|
pop edi
|
|
pop ebx
|
|
pop ecx
|
|
|
|
jmp _joy_read_stick_friendly_retry
|
|
|
|
NoInts:
|
|
call joy_get_timer ; Returns counter in EAX
|
|
|
|
xchg eax, dword [LastTick]
|
|
cmp eax, dword [LastTick]
|
|
jb @@f3
|
|
sub eax, dword [LastTick]
|
|
@@f3: ; Higher...
|
|
add dword [TotalTicks], eax
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae timed_out_f
|
|
jmp again_f
|
|
|
|
flip_f: and eax, 01111b ; Only care about axis values
|
|
mov [edi], eax ; Record what channel(s) flipped
|
|
add edi, 4
|
|
xor bl, al ; Unmark the channels that just tripped
|
|
|
|
call joy_get_timer ; Returns counter in EAX
|
|
mov [edi], eax ; Record the time this channel flipped
|
|
add edi, 4
|
|
inc bh ; Increment number of events
|
|
|
|
cmp bl, 0
|
|
jne again_f ; If there are more channels to read, keep looping
|
|
|
|
timed_out_f:
|
|
sti
|
|
|
|
movzx eax, bh ; Return number of events
|
|
|
|
pop edi
|
|
pop ebx
|
|
pop ecx
|
|
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
|
|
|
|
global _joy_read_stick_asm2
|
|
|
|
_joy_read_stick_asm2:
|
|
push ebx
|
|
push edi
|
|
|
|
mov ebx,[esp+12]
|
|
mov edi,[esp+16]
|
|
mov ecx,[esp+20]
|
|
|
|
; ebx = read mask
|
|
; edi = pointer to event buffer
|
|
; ecx = timeout value
|
|
; returns in eax the number of events
|
|
mov dword [_joy_bogus_reading], 0
|
|
|
|
and ebx, 01111b ; Make sure we only check the right values
|
|
; number of events we found will be in bh, so this also clears it to zero.
|
|
|
|
mov dx, [_JOY_PORT]
|
|
|
|
cli ; disable interrupts while reading time...
|
|
call joy_get_timer ; Returns counter in EAX
|
|
sti ; enable interrupts after reading time...
|
|
mov dword [LastTick], eax
|
|
|
|
waitforstable: in al, dx
|
|
and al, bl
|
|
jz ready ; Wait for the port in question to be done reading...
|
|
|
|
cli ; disable interrupts while reading time...
|
|
call joy_get_timer ; Returns counter in EAX
|
|
sti ; enable interrupts after reading time...
|
|
xchg eax, dword [LastTick]
|
|
cmp eax, dword [LastTick]
|
|
jb @@f4
|
|
sub eax, dword [LastTick]
|
|
@@f4: ; Higher...
|
|
add dword [TotalTicks], eax
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae ready
|
|
jmp waitforstable
|
|
|
|
ready:
|
|
cli
|
|
mov al, 0ffh
|
|
out dx, al ; Start joystick a readin'
|
|
|
|
call joy_get_timer ; Returns counter in EAX
|
|
mov dword [LastTick], eax
|
|
mov dword [TotalTicks], 0
|
|
|
|
mov [edi], eax ; Store initial count
|
|
add edi, 4
|
|
|
|
again: in al, dx ; Read Joystick port
|
|
not al
|
|
and al, bl ; Mask off channels we don't want to read
|
|
jnz flip ; See if any of the channels flipped
|
|
|
|
call joy_get_timer ; Returns counter in EAX
|
|
|
|
xchg eax, dword [LastTick]
|
|
cmp eax, dword [LastTick]
|
|
jb @@f5
|
|
sub eax, dword [LastTick]
|
|
@@f5: ; Higher...
|
|
add dword [TotalTicks], eax
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae timedout
|
|
jmp again
|
|
|
|
flip: and eax, 01111b ; Only care about axis values
|
|
mov [edi], eax ; Record what channel(s) flipped
|
|
add edi, 4
|
|
xor bl, al ; Unmark the channels that just tripped
|
|
|
|
call joy_get_timer ; Returns counter in EAX
|
|
mov [edi], eax ; Record the time this channel flipped
|
|
add edi, 4
|
|
inc bh ; Increment number of events
|
|
|
|
cmp bl, 0
|
|
jne again ; If there are more channels to read, keep looping
|
|
|
|
timedout:
|
|
movzx eax, bh ; Return number of events
|
|
|
|
sti
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
|
|
global _joy_read_stick_polled2
|
|
|
|
_joy_read_stick_polled2:
|
|
push ebx
|
|
push edi
|
|
|
|
mov ebx,[esp+12]
|
|
mov edi,[esp+16]
|
|
mov ecx,[esp+20]
|
|
|
|
; ebx = read mask
|
|
; edi = pointer to event buffer
|
|
; ecx = timeout value
|
|
; returns in eax the number of events
|
|
mov dword [_joy_bogus_reading], 0
|
|
|
|
and ebx, 01111b ; Make sure we only check the right values
|
|
; number of events we found will be in bh, so this also clears it to zero.
|
|
|
|
mov dx, [_JOY_PORT]
|
|
|
|
mov dword [TotalTicks], 0
|
|
|
|
waitforstable1: in al, dx
|
|
and al, bl
|
|
jz ready1 ; Wait for the port in question to be done reading...
|
|
|
|
inc dword [TotalTicks]
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae ready1
|
|
jmp waitforstable1
|
|
ready1:
|
|
cli
|
|
mov al, 0ffh
|
|
out dx, al ; Start joystick a readin'
|
|
|
|
mov dword [TotalTicks], 0
|
|
|
|
mov dword [edi], 0 ; Store initial count
|
|
add edi, 4
|
|
|
|
again1: in al, dx ; Read Joystick port
|
|
not al
|
|
and al, bl ; Mask off channels we don't want to read
|
|
jnz flip1 ; See if any of the channels flipped
|
|
|
|
inc dword [TotalTicks]
|
|
cmp dword [TotalTicks], ecx ; Timeout at 1/200'th of a second
|
|
jae timedout1
|
|
jmp again1
|
|
|
|
flip1: and eax, 01111b ; Only care about axis values
|
|
mov [edi], eax ; Record what channel(s) flipped
|
|
add edi, 4
|
|
xor bl, al ; Unmark the channels that just tripped
|
|
|
|
mov eax, dword [TotalTicks]
|
|
mov [edi], eax ; Record the time this channel flipped
|
|
add edi, 4
|
|
inc bh ; Increment number of events
|
|
|
|
cmp bl, 0
|
|
jne again1 ; If there are more channels to read, keep looping
|
|
|
|
timedout1:
|
|
movzx eax, bh ; Return number of events
|
|
|
|
sti
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
global _joy_read_stick_bios2
|
|
|
|
_joy_read_stick_bios2:
|
|
push ebx
|
|
push edi
|
|
|
|
mov ebx,[esp+12]
|
|
mov edi,[esp+16]
|
|
mov ecx,[esp+20]
|
|
; ebx = read mask
|
|
; edi = pointer to event buffer
|
|
; ecx = timeout value
|
|
; returns in eax the number of events
|
|
|
|
mov dword [_joy_bogus_reading], 0
|
|
|
|
pusha
|
|
|
|
mov dword [edi], 0
|
|
|
|
mov eax, 08400h
|
|
mov edx, 1
|
|
cli
|
|
int 15h
|
|
sti
|
|
|
|
mov dword [edi+4], 1 ; Axis 1
|
|
and eax, 0ffffh
|
|
mov [edi+8], eax ; Axis 1 value
|
|
|
|
mov dword [edi+12], 2 ; Axis 2
|
|
and ebx, 0ffffh
|
|
mov [edi+16], ebx ; Axis 2 value
|
|
|
|
mov dword [edi+20], 4 ; Axis 3
|
|
and ecx, 0ffffh
|
|
mov [edi+24], ecx ; Axis 3 value
|
|
|
|
mov dword [edi+28], 8 ; Axis 3
|
|
and edx, 0ffffh
|
|
mov [edi+32], edx ; Axis 3 value
|
|
|
|
popa
|
|
mov eax, 4 ; 4 events
|
|
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
|
|
|
|
global _joy_read_buttons_bios2
|
|
|
|
_joy_read_buttons_bios2:
|
|
; returns in eax the button settings
|
|
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
mov eax, 08400h
|
|
mov edx, 0 ; Read switches
|
|
int 15h
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
|
|
shr eax, 4
|
|
not eax
|
|
and eax, 01111b
|
|
ret
|
|
global _joy_read_buttons_bios_end2
|
|
_joy_read_buttons_bios_end2: ; to calculate _joy_read_buttons_bios size
|
|
|