📄 llevtstg.asm
字号:
PAGE 56,132
TITLE LLEVTSTG - Low-level joystick support
;***
; LLEVTSTG - Low-level joystick support
;
; Copyright <C> 1987, Microsoft Corporation
;
;Purpose:
;
;******************************************************************************
INCLUDE switch.inc
INCLUDE rmacros.inc
useSeg _BSS
useSeg _DATA
useSeg EV_TEXT
INCLUDE seg.inc
INCLUDE ibmunv.inc
INCLUDE idmac.inc ; debugging macros
INCLUDE intmac.inc
INCLUDE event.inc ; bit flag constants
sBegin _DATA
TRIGSA DB 0,TRIG_A1 ;TRIGGER 'A1 Save Status & Mask
DB 0,TRIG_B1 ;TRIGGER 'B1 Save Status & Mask
DB 0,TRIG_A2 ;TRIGGER 'A2 Save Status & Mask
DB 0,TRIG_B2 ;TRIGGER 'B2 Save Status & Mask
sEnd _DATA
sBegin _BSS
externB b$MACHID ; machine identification
STIKAX DB 4 DUP(?) ;STICK 'A' x,y - 'B' x,y Positions
sEnd _BSS
sBegin EV_TEXT
assumes CS,EV_TEXT
externNP B$TrapEvent ;routine to set global event flag
externNP B$SetClockInt ;routine to install clock interrupt
SUBTTL B$RDTRIG - Read Joystick Trigger Flag.
PAGE
;***
;B$RDTRIG - Read Joystick Trigger Flag.
;OEM-interface routine
;
;Purpose:
; Determines the status of a Joystick Trigger. This routine
; can return either the current status of the trigger (AH=0)
; or a latched status (AH=1). The latched status will indicate
; if the joystick trigger has been pressed since the last time
; this routine was called.
;
; See the documentation for B$POLLEV for a description of the
; event and trapping mechanisms.
;
;Entry:
; [AL]=joy-stick trigger id (0..n)
;
; [AH]=current/latched flag
; [AH]=0 request current status
; [AH]=1 request latched status
;
;Exit:
; [AL]=0 if trigger is not pressed (current) or has not been pressed
; since last call to B$RDTRIG (latched).
; [AL]=-1 if trigger is pressed (current) or has been pressed since last
; call to B$RDTRIG (latched).
;
; PSW.C set indicates that there was an error, else PSW.C is clear.
;
;Uses:
; per convention
;
;Preserves:
; BX, CX, DX
;
;Exceptions:
; None.
;****
cProc B$RDTRIG,<NEAR,PUBLIC>
cBegin
CALL B$SetClockInt ; check if CLOCK_INT has been installed
;if not install it
PUSH BX
PUSH CX
PUSH AX
XOR BX,BX
MOV BL,AL ;place i.d. in bx
SHL BX,1
TEST AH,1 ;Read Status or Trigger?
JNZ $STF_S ;Brif Status (0, 2, 4 or 6).
MOV CH,TRIGSA[BX+1] ;Get Trigger Mask for read
CALL RTRGST ;Read Trigger A1,B1,A2 or B2 in [CL]
MOV AL,CL
JMP SHORT $STF_RET ;Return: -1 if fired, 0 if not.
$STF_S:
MOV AL,BYTE PTR TRIGSA[BX] ;Get Trigger A or B value.
MOV BYTE PTR TRIGSA[BX],0 ;Tell INT routine we read it.
;Return: -1 if fired, 0 if not.
$STF_RET:
POP BX ;restore original ah
MOV AH,BH
POP CX
POP BX
CLC ;carry clear since no error
cEnd
;***
;B$RDSTIK - Read Joystick Coordinates
;OEM-interface routine
;
;Purpose:
; Return either the X or Y coordinate of a joystick. The coordinate
; is a system dependent signed value, which may simply be -1, 0 or 1.
;
;Entry:
; [AL]=Function to be performed as follows:
; 0 = Return the x coordinate for joystick A.
; 1 = Return the y coordinate for joystick A.
; 2 = Return the x coordinate for joystick B.
; 3 = Return the y coordinate for joystick B.
; n = If n is even then n is x coordinate for joystick (n+2)/2
; else n is y coordinate for joystick (n+1)/2.
;
;Exit:
; PSW.C is set indicates an error ([AL] represents a joystick number
; that is too large)
; PSW.C is reset otherwise
;
; [BX] = Signed integer result.
;
;Uses:
; Per convention.
;
;Preserves:
; AX, CX, DX
;
;Exceptions:
; None.
;****
cProc B$RDSTIK,<NEAR,PUBLIC>,<AX,CX,DX>
cBegin
CALL B$SetClockInt ; check if CLOCK_INT has been installed
;if not install it
MOV BL,AL ;place offset in bx
XOR BH,BH ;clear high byte
CMP BX,4 ;Out of Range?
JNB STICK_ERROR ;Yes, complain..
CALL RSTICK ;read stick
MOV BL,STIKAX[BX] ;get it
XOR BH,BH ;(clears carry)
JMP SHORT StickExit ; return with carry clear
STICK_ERROR:
STC ; indicate error
StickExit:
cEnd ; restore registers & return
;***
;RSTICK - Reads the 4 Potentiometers. Typically, each
; value will range from 0 to 200 depending upon
; the R values of the Pots.
;
;Entry: None
;
;Exit: STIKAX,AY = x,y Coordinates of Channel A.
; STIKBX,BY = x,y Coordinates of Channel B.
;****
cProc RSTICK,<NEAR>,<AX,BX,DX>
cBegin
CMP b$MACHID,0FCH ;is this a PC-AT?
JE AT_STICK ; brif so
MOV DX,GAMECD ;Game Card
MOV CX,257 ;Counter, adjusted by -2.
MOV BX,0FH ;Pot Mask.
CLI ;No Interrups During Sample
PAUSE
OUT DX,AL ;Strobe to start
SAMPL:
PAUSE
IN AL,DX ;Get the Pot Values
AND AL,0FH ;Isolate Pot Value
CMP AL,BL ;Set ZF if no change.
LOOPZ SAMPL ;Loop till change or count exhausted.
JCXZ SAMPL1 ;Brif count done, else got change.
XOR AL,BL ;[AL] = one(s) that changed state
MOV AH,CL ;[AH] = compl of count.
PUSH AX ;Save count/mask
INC BH ;Push count +1.
XOR BL,AL ;[BL] = New Mask.
JMP SHORT SAMPL
SAMPL1:
ENABLE ;Interrupts back on
OR BH,BH
JZ SAMPLX ;Brif no Game Card.
MOV DL,BH ;[DL] = No. to POP.
SAMPL2:
MOV BX,OFFSET DGROUP:STIKAX ;Pot value save area.
MOV CX,4 ;Shift count (4 pots).
POP AX ;Get count/mask.
NOT AH ;Compl for true count.
ADD AH,DL ;Adjust for time in sample loop.
SAMPL3:
SHR AL,1 ;Has this Paddle changed State?
JNB SAMPL4 ;Brif Not..
MOV [BX],AH ;Yes, store current count
SAMPL4:
INC BX ;Point to next Location
LOOP SAMPL3 ;Until all 4 done...
DEC DL ;No. to POP -1
JNZ SAMPL2 ;Brif more Values.
SAMPLX:
cEnd
; read joystick coordinates for PC-AT
AT_STICK:
MOV AH,84H ;Joystick support
MOV DX,1 ;read joystick pots
INT 21D
MOV STIKAX,AL ;A(x)
MOV STIKAX+1,BL ;A(y)
MOV STIKAX+2,CL ;B(x)
MOV STIKAX+3,DL ;B(y)
JMP SHORT SAMPLX
;***
;B$JoystInt STRIG Update
;
; Called by Timer Interupt AFTER updating the
; time-of-day only if joystick code present.
;
; CLOCKTIC polls the PEN Status (if ON) and stores
; new values. Then Joystick TRIGGERS (if ON) and
; stores their values if fired since last time
; read with the STRIG(0), STRIG(2), STRIG(4) or
; STRIG(6) Statement.
;
; NOTE: Rom clock interrupt routine saved [AX],[DX],[DS]
;****
cProc B$JoystInt,<NEAR,PUBLIC>,<BX,CX>
cBegin
MOV BX,OFFSET DGROUP:TRIGSA ;Look at Trigger 'A' status.
MOV CX,4 ;no. of triggers to read
TRGIN2:
CMP BYTE PTR [BX],0 ;Trigger x been read?
JNZ TRGIN3 ;No, try next Trigger
PUSH CX
MOV CH,[BX+1] ;Get Mask for this Trigger
CALL RTRGST ; Read Trigger 'A' or 'B'
MOV [BX],CL ; Store value
CMP CL,-1 ; has trigger been pressed?
JNZ NoTrig ; brif not
MOV AX,BX ; AL = trap number for B$TrapEvent
ADD AX,STGOFF*2 + OFFSET DGROUP:TRIGSA
SHR AL,1
CALL B$TrapEvent ; set global event flag
NoTrig:
POP CX
TRGIN3:
INC BX
INC BX ;Next trigger status loc.
LOOP TRGIN2 ;Until all triggers tested
cEnd ; restore regs & return
cProc RTRGST,<NEAR>,<DX>
cBegin
CMP b$MACHID,0FCH ;is this a PC-AT?
JNE PCTRIG ;br. if not
MOV AH,84H ;Joystick support
XOR DX,DX ;read joystick triggers
INT 15h ; [AL] = trigger values
JMP SHORT ALLTRIG ;skip PC trigger read
PCTRIG:
MOV DX,GAMECD
PAUSE
IN AL,DX ;Read Joysticks/Triggers
ALLTRIG:
AND AL,CH ;Mask to Trigger 'A' or 'B'
DEC AL ;-1 if down.
CBW ; 0 if up.
MOV CL,AH ;Return in [CL]
cEnd ; restore regs & return
sEnd EV_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -