blob: 0ff1ecf55d30d7d6e0c08c5c8f3560024997a632 [file] [log] [blame]
;****************************************************************************
;*
;* SciTech OS Portability Manager Library
;*
;* ========================================================================
;*
;* The contents of this file are subject to the SciTech MGL Public
;* License Version 1.0 (the "License"); you may not use this file
;* except in compliance with the License. You may obtain a copy of
;* the License at http://www.scitechsoft.com/mgl-license.txt
;*
;* Software distributed under the License is distributed on an
;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
;* implied. See the License for the specific language governing
;* rights and limitations under the License.
;*
;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
;*
;* The Initial Developer of the Original Code is SciTech Software, Inc.
;* All Rights Reserved.
;*
;* ========================================================================
;*
;* Language: 80386 Assembler
;* Environment: Intel x86, any OS
;*
;* Description: Assembly language support routines for reading analogue
;* joysticks.
;*
;****************************************************************************
ideal
include "scitech.mac" ; Memory model macros
ifdef flatmodel
header _joy ; Set up memory model
begcodeseg _joy ; Start of code segment
;----------------------------------------------------------------------------
; initTimer
;----------------------------------------------------------------------------
; Sets up 8253 timer 2 (PC speaker) to start timing, but not produce output.
;----------------------------------------------------------------------------
cprocstatic initTimer
; Start timer 2 counting
in al,61h
and al,0FDh ; Disable speaker output (just in case)
or al,1
out 61h,al
; Set the timer 2 count to 0 again to start the timing interval.
mov al,10110100b ; set up to load initial (timer 2)
out 43h,al ; timer count
sub al,al
out 42h,al ; load count lsb
out 42h,al ; load count msb
ret
cprocend
;----------------------------------------------------------------------------
; readTimer2
;----------------------------------------------------------------------------
; Reads the number of ticks from the 8253 timer chip using channel 2 (PC
; speaker). This is non-destructive and does not screw up other libraries.
;----------------------------------------------------------------------------
cprocstatic readTimer
xor al,al ; Latch timer 0 command
out 43h,al ; Latch timer
in al,42h ; least significant byte
mov ah,al
in al,42h ; most significant byte
xchg ah,al
and eax,0FFFFh
ret
cprocend
;----------------------------------------------------------------------------
; exitTimer
;----------------------------------------------------------------------------
; Stops the 8253 timer 2 (PC speaker) counting
;----------------------------------------------------------------------------
cprocstatic exitTimer
; Stop timer 2 from counting
push eax
in al,61h
and al,0FEh
out 61h,al
; Some programs have a problem if we change the control port; better change it
; to something they expect (mode 3 - square wave generator)...
mov al,0B6h
out 43h,al
pop eax
ret
cprocend
;----------------------------------------------------------------------------
; int _EVT_readJoyAxis(int jmask,int *axis);
;----------------------------------------------------------------------------
; Function to poll the joystick to read the current axis positions.
;----------------------------------------------------------------------------
cprocstart _EVT_readJoyAxis
ARG jmask:UINT, axis:DPTR
LOCAL firstTick:UINT, lastTick:UINT, totalTicks:UINT = LocalSize
enter_c
mov ebx,[jmask]
mov edi,[axis]
mov ecx,(1193180/100)
and ebx,01111b ; Mask out supported axes
mov dx,201h ; DX := joystick I/O port
call initTimer ; Start timer 2 counting
call readTimer ; Returns counter in EAX
mov [lastTick],eax
@@WaitStable:
in al,dx
and al,bl ; Wait for the axes in question to be
jz @@Stable ; done reading...
call readTimer ; Returns counter in EAX
xchg eax,[lastTick]
cmp eax,[lastTick]
jb @@1
sub eax,[lastTick]
@@1: add [totalTicks],eax
cmp [totalTicks],ecx ; Check for timeout
jae @@Stable
jmp @@WaitStable
@@Stable:
mov al,0FFh
out dx,al ; Start joystick reading
call initTimer ; Start timer 2 counting
call readTimer ; Returns counter in EAX
mov [firstTick],eax ; Store initial count
mov [lastTick],eax
mov [DWORD totalTicks],0
cli
@@PollLoop:
in al,dx ; Read Joystick port
not al
and al,bl ; Mask off channels we don't want to read
jnz @@AxisFlipped ; See if any of the channels flipped
call readTimer ; Returns counter in EAX
xchg eax,[lastTick]
cmp eax,[lastTick]
jb @@2
sub eax,[lastTick]
@@2: add [totalTicks],eax
cmp [totalTicks],ecx ; Check for timeout
jae @@TimedOut
jmp @@PollLoop
@@AxisFlipped:
xor esi,esi
mov ah,1
test al,ah
jnz @@StoreCount ; Joystick 1, X axis flipped
add esi,4
mov ah,2
test al,ah
jnz @@StoreCount ; Joystick 1, Y axis flipped
add esi,4
mov ah,4
test al,ah
jnz @@StoreCount ; Joystick 2, X axis flipped
add esi,4 ; Joystick 2, Y axis flipped
mov ah,8
@@StoreCount:
or bh,ah ; Indicate this axis is active
xor bl,ah ; Unmark the channels that just tripped
call readTimer ; Returns counter in EAX
xchg eax,[lastTick]
cmp eax,[lastTick]
jb @@3
sub eax,[lastTick]
@@3: add [totalTicks],eax
mov eax,[totalTicks]
mov [edi+esi],eax ; Record the time this channel flipped
cmp bl,0 ; If there are more channels to read,
jne @@PollLoop ; keep looping
@@TimedOut:
sti
call exitTimer ; Stop timer 2 counting
movzx eax,bh ; Return the mask of working axes
leave_c
ret
cprocend
;----------------------------------------------------------------------------
; int _EVT_readJoyButtons(void);
;----------------------------------------------------------------------------
; Function to poll the current joystick buttons
;----------------------------------------------------------------------------
cprocstart _EVT_readJoyButtons
mov dx,0201h
in al,dx
shr al,4
not al
and eax,0Fh
ret
cprocend
endcodeseg _joy
endif
END ; End of module