⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sw32.asm

📁 linux下的任天堂模拟器代码。供大家参考。
💻 ASM
字号:
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach );;http://www.zsnes.com;http://sourceforge.net/projects/zsnes;https://zsnes.bountysource.com;;This program is free software; you can redistribute it and/or;modify it under the terms of the GNU General Public License;version 2 as published by the Free Software Foundation.;;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+SECTION .dataSW1 dd 0                ;SW #1's button statusSW2 dd 0                ;SW #2's button statusSW3 dd 0                ;SW #3's button statusSW4 dd 0                ;SW #4's button statusSWCount dd 1            ;Tell the driver how many sidewinders are presentSWSetup 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 statementgDump 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)SECTION .text;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 destroyedreadSideWinder:  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 SMWDoneENDP%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%endmacroDoModeB:  xor ebx,ebx                 ;Initialize output  xor eax,eax  SWRepeat 0  SWRepeat 1  SWRepeat 2  SWRepeat 3  SWRepeat 4  xor ebx,0FFFEh  retDoModeA:  xor ebx,ebx                 ;Clear output  mov ecx,15 ;bit countALP:  mov al,[bDump+ebp]  inc ebp  shl al,3  rcr ebx,1  dec ecx  jg  ALP  shr ebx,16  xor ebx,0FFFEh  ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -