First release of ZSNES sources
This commit is contained in:
330
zsnes/src/dos/sw32.asm
Normal file
330
zsnes/src/dos/sw32.asm
Normal file
@@ -0,0 +1,330 @@
|
||||
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
|
||||
;
|
||||
;This program is free software; you can redistribute it and/or
|
||||
;modify it under the terms of the GNU General Public License
|
||||
;as published by the Free Software Foundation; either
|
||||
;version 2 of the License, or (at your option) any later
|
||||
;version.
|
||||
;
|
||||
;This program is distributed in the hope that it will be useful,
|
||||
;but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;GNU General Public License for more details.
|
||||
;
|
||||
;You should have received a copy of the GNU General Public License
|
||||
;along with this program; if not, write to the Free Software
|
||||
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;32-bit DOS-Mode driver for the Microsoft Sidewinder Gamepad
|
||||
;Multi-SW Version 1.5
|
||||
;(C) 1997, 1998 Robert William Grubbs, All Rights Reserved
|
||||
;Latest revision 1/20/98
|
||||
; Driver Source code Include file
|
||||
|
||||
;C-linkable, rewrote decoder -sardu
|
||||
|
||||
;Flat memory mode (Protected mode extender required! Tested with DOS32)
|
||||
;Tested with TASM 4.0+
|
||||
|
||||
|
||||
SW1 dd 0 ;SW #1's button status
|
||||
SW2 dd 0 ;SW #2's button status
|
||||
SW3 dd 0 ;SW #3's button status
|
||||
SW4 dd 0 ;SW #4's button status
|
||||
SWCount dd 1 ;Tell the driver how many sidewinders are present
|
||||
SWSetup dd 0 ;Tell the driver what polling mode to use
|
||||
; 0=Interrupts disabled, Multiple OUT statements
|
||||
; 1=Interrupts disabled, Single OUT statement
|
||||
; 2=Interrupts enabled, Multiple OUT statements
|
||||
; 3=Interrupts enabled, Single OUT statement
|
||||
|
||||
gDump times 100h db 0 ;SW Status dump buffer (space for 256 bytes, uses 200)
|
||||
bDump times 80h db 0 ;buffer to hold button data (Modes A and B, all SW)
|
||||
|
||||
;This macro calculates parity for the buttons and compares it to the SW's
|
||||
; parity bit. If they don't match, the button data is discarded.
|
||||
%macro ParityCheckSW 1
|
||||
mov ecx,ebx ;duplicate button status
|
||||
xor cl,ch ;
|
||||
jpe %%ParChkSW
|
||||
mov [%1],ebx ;update button status for SW #n
|
||||
%%ParChkSW ;done
|
||||
%endmacro
|
||||
|
||||
;The main subroutine; this is the important one; bow down before it
|
||||
;IN: None
|
||||
;Out: SWx=buttons (bit 0=null 1=up 2=dn 3=rt 4=lt 5=A 6=B 7=C 8=X)
|
||||
; (9=Y 10=Z 11=L 12=R 13=St 14=M 15=Parity)
|
||||
;No registers destroyed
|
||||
|
||||
readSideWinder:
|
||||
pushad
|
||||
|
||||
mov ecx,200 ;dump buffer fill size
|
||||
mov ebx,gDump ;initial dump pointer
|
||||
mov edx,0201h ;joystick port
|
||||
|
||||
cmp dword[SWSetup],0
|
||||
jne NotSW0
|
||||
cli ;Disable interrupts (required to avoid jitter)
|
||||
GetSWDataLoop: ;
|
||||
out dx,al ;trigger joystick port
|
||||
in al,dx ;read SW status byte
|
||||
mov [ebx],al ;dump status byte
|
||||
inc ebx ;increment dump pointer
|
||||
dec ecx
|
||||
jnz GetSWDataLoop
|
||||
sti ;Re-enable interrupts
|
||||
jmp SWPollDone
|
||||
|
||||
NotSW0:
|
||||
cmp dword[SWSetup],1
|
||||
jne NotSW1
|
||||
cli ;Disable interrupts (required to avoid jitter)
|
||||
out dx,al ;trigger joystick port
|
||||
GetSWDataLoop1: ;
|
||||
in al,dx ;read SW status byte
|
||||
mov [ebx],al ;dump status byte
|
||||
inc ebx ;increment dump pointer
|
||||
dec ecx
|
||||
jnz GetSWDataLoop1
|
||||
sti ;Re-enable interrupts
|
||||
jmp SWPollDone
|
||||
|
||||
NotSW1:
|
||||
cmp dword[SWSetup],2
|
||||
jne NotSW2
|
||||
GetSWDataLoop2: ;
|
||||
out dx,al ;trigger joystick port
|
||||
in al,dx ;read SW status byte
|
||||
mov [ebx],al ;dump status byte
|
||||
inc ebx ;increment dump pointer
|
||||
dec ecx
|
||||
jnz GetSWDataLoop2
|
||||
jmp SWPollDone
|
||||
|
||||
NotSW2:
|
||||
;default all others to SWStatus=3
|
||||
out dx,al ;trigger joystick port
|
||||
GetSWDataLoop3: ;
|
||||
in al,dx ;read SW status byte
|
||||
mov [ebx],al ;dump status byte
|
||||
inc ebx ;increment dump pointer
|
||||
dec ecx
|
||||
jnz GetSWDataLoop3
|
||||
|
||||
SWPollDone:
|
||||
|
||||
mov ecx,0 ;tick count
|
||||
mov esi,1 ;initialize output mask
|
||||
mov ebx,0 ;initialize output
|
||||
mov edi,0 ;initialize input pointer
|
||||
|
||||
;My current method of cycle detection is to look for 15 highs in a row on
|
||||
; the strobe line. Cycle ends is detected by 15 lows in a row.
|
||||
;Mode A has 15 strobes in a cycle, Mode B has 5.
|
||||
; Note that the 15 highs/lows for cycle detection may be too high for slow
|
||||
; machines. I havn't seen a problem yet, but it may exist...
|
||||
;Multiple Sidewinder data complicates things. Each additional SW tags
|
||||
; another set of strobes to the cycle, 5 more in mode B, 15 more in mode A.
|
||||
; Detecting extra SW gamepad data is fairly simple: count the number of
|
||||
; strobes. If it is a multiple of 5, you're in mode B and can divide by 5
|
||||
; to get the total number of gamepads. If it's divisible by 15, use mode A.
|
||||
; However, this method cannot distinguish between mode A for one SW and mode
|
||||
; B for three SW. In that case, the SWCount variable must be set correctly.
|
||||
|
||||
FindCycle:
|
||||
mov al,[gDump+edi] ;get next status byte
|
||||
inc edi ;increment input pointer
|
||||
cmp edi,200 ;test for end of status block
|
||||
je SWNoFind ;if it's the end, quit sub with error
|
||||
test al,00010000b ;Check for nonzero bits
|
||||
jnz WMFCS1 ;
|
||||
xor ecx,ecx ;if zero, reset tick count
|
||||
jmp FindCycle ;can't be pre-cycle
|
||||
WMFCS1: ;Possibly pre-cycle
|
||||
inc ecx ;increment tick count
|
||||
cmp ecx,15 ;test for sufficient ticks for cycle start
|
||||
jne FindCycle ;if insufficient, get next status byte
|
||||
;Yippie! it found a (probable) cycle!
|
||||
|
||||
mov ebp,0 ;initialize bDump index (strobe count)
|
||||
|
||||
FindStrobeLow: ;Search for leading edge of data strobe
|
||||
mov al,[gDump+edi] ;get next status byte
|
||||
inc edi ;increment input pointer
|
||||
cmp edi,200 ;test for end of status block
|
||||
je SWNoFind ;if it's the end, quit sub with error
|
||||
test al,00010000b ;get "strobe" bit
|
||||
jnz SHORT FindStrobeLow ;if it isn't zero, we're not there yet
|
||||
xor ecx,ecx ;initialize cycle end test count
|
||||
|
||||
FindStrobeHigh:
|
||||
inc ecx ;increment zero count
|
||||
cmp ecx,0fh ;is it 15?
|
||||
je SWModeCheck ;if so, goto mode check
|
||||
mov al,[gDump+edi] ;get next status byte
|
||||
inc edi ;increment input pointer
|
||||
cmp edi,200 ;test for end of status block
|
||||
je SWNoFind ;if it's the end, quit sub with error
|
||||
test al,00010000b ;get "strobe" bit
|
||||
jz FindStrobeHigh ;if it is zero, we're not there yet
|
||||
;if not, we're there! data bit is valid (probably)
|
||||
mov [bDump+ebp],al ;preserve data for button decoding
|
||||
inc ebp ;increment strobe count/bDump index
|
||||
jmp FindStrobeLow ;wait for the next button
|
||||
|
||||
SMWDone:
|
||||
SWNoFind:
|
||||
popad
|
||||
ret ;return to calling procedure
|
||||
|
||||
SWModeCheck: ;Check strobe count to identify mode and # of SW
|
||||
cmp ebp,15 ;Is it Mode A with 1 Sidewinder or B with 3?
|
||||
je ModeA1
|
||||
cmp ebp,5 ;Is it Mode B with 1 Sidewinders?
|
||||
je ModeB1
|
||||
cmp ebp,30 ;Is it Mode A with 2 Sidewinders?
|
||||
je ModeA2
|
||||
cmp ebp,10 ;Is it Mode B with 2 Sidewinders?
|
||||
je near ModeB2
|
||||
cmp ebp,45 ;Is it Mode A with 3 Sidewinders?
|
||||
je near ModeA3
|
||||
cmp ebp,60 ;Is it Mode A with 4 Sidewinders?
|
||||
je near ModeA4
|
||||
cmp ebp,20 ;Is it Mode B with 4 Sidewinders?
|
||||
je near ModeB4
|
||||
jmp SHORT SWNoFind ;Any other # of strobes is invalid data
|
||||
|
||||
ModeB1:
|
||||
xor ebp,ebp
|
||||
call DoModeB
|
||||
ParityCheckSW SW1
|
||||
jmp SMWDone
|
||||
|
||||
ModeA1:
|
||||
cmp dword [SWCount],3
|
||||
je near ModeB3
|
||||
xor ebp,ebp
|
||||
call DoModeA
|
||||
ParityCheckSW SW1
|
||||
jmp SMWDone
|
||||
|
||||
ModeA2:
|
||||
xor ebp,ebp
|
||||
call DoModeA
|
||||
ParityCheckSW SW1
|
||||
mov ebp,15
|
||||
call DoModeA
|
||||
ParityCheckSW SW2
|
||||
jmp SMWDone
|
||||
|
||||
ModeA3:
|
||||
xor ebp,ebp
|
||||
call DoModeA
|
||||
ParityCheckSW SW1
|
||||
mov ebp,15
|
||||
call DoModeA
|
||||
ParityCheckSW SW2
|
||||
mov ebp,30
|
||||
call DoModeA
|
||||
ParityCheckSW SW3
|
||||
jmp SMWDone
|
||||
|
||||
ModeA4:
|
||||
xor ebp,ebp
|
||||
call DoModeA
|
||||
ParityCheckSW SW1
|
||||
mov ebp,15
|
||||
call DoModeA
|
||||
ParityCheckSW SW2
|
||||
mov ebp,30
|
||||
call DoModeA
|
||||
ParityCheckSW SW3
|
||||
mov ebp,45
|
||||
call DoModeA
|
||||
ParityCheckSW SW4
|
||||
jmp SMWDone
|
||||
|
||||
ModeB2:
|
||||
xor ebp,ebp
|
||||
call DoModeB
|
||||
ParityCheckSW SW1
|
||||
mov ebp,5
|
||||
call DoModeB
|
||||
ParityCheckSW SW2
|
||||
jmp SMWDone
|
||||
|
||||
ModeB3:
|
||||
xor ebp,ebp
|
||||
call DoModeB
|
||||
ParityCheckSW SW1
|
||||
mov ebp,5
|
||||
call DoModeB
|
||||
ParityCheckSW SW2
|
||||
mov ebp,10
|
||||
call DoModeB
|
||||
ParityCheckSW SW3
|
||||
jmp SMWDone
|
||||
|
||||
ModeB4:
|
||||
xor ebp,ebp
|
||||
call DoModeB
|
||||
ParityCheckSW SW1
|
||||
mov ebp,5
|
||||
call DoModeB
|
||||
ParityCheckSW SW2
|
||||
mov ebp,10
|
||||
call DoModeB
|
||||
ParityCheckSW SW3
|
||||
mov ebp,15
|
||||
call DoModeB
|
||||
ParityCheckSW SW4
|
||||
jmp SMWDone
|
||||
ENDP
|
||||
|
||||
%macro SWRepeat 1
|
||||
mov al,[bDump+ebp+%1]
|
||||
shr al,5 ;get upper 3 bits
|
||||
shl eax,1+3*%1 ;shift into place
|
||||
or ebx,eax ;or into output
|
||||
%endmacro
|
||||
|
||||
DoModeB:
|
||||
xor ebx,ebx ;Initialize output
|
||||
xor eax,eax
|
||||
|
||||
SWRepeat 0
|
||||
SWRepeat 1
|
||||
SWRepeat 2
|
||||
SWRepeat 3
|
||||
SWRepeat 4
|
||||
|
||||
xor ebx,0FFFEh
|
||||
ret
|
||||
|
||||
DoModeA:
|
||||
xor ebx,ebx ;Clear output
|
||||
mov ecx,15 ;bit count
|
||||
|
||||
ALP:
|
||||
mov al,[bDump+ebp]
|
||||
inc ebp
|
||||
shl al,3
|
||||
rcr ebx,1
|
||||
dec ecx
|
||||
jg ALP
|
||||
|
||||
shr ebx,16
|
||||
xor ebx,0FFFEh
|
||||
ret
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user