📄 llaevt.asm
字号:
cEnd
;***
;B$SetClockInt - Install CLOCKTIC interrupt if not already installed
;OEM-interface routine
;
;Purpose:
; This routine checks to see if the CLOCKTIC has been
; installed or not. If not installed it installs it.
;
;Entry:
; None.
;
;Exit:
; None.
;
;Uses:
; Per convention
;
;Exceptions:
; None.
;****
cProc B$SetClockInt,<NEAR,PUBLIC>
cBegin
TEST b$EventFlags,TimerInst ; timer interrupt installed yet ?
JZ SET_IT ;Brif not -- install it now
NearRet: ; label to a near return
RET
SET_IT:
PUSH AX
PUSH DX
PUSH DS
IN AL,MSKREG ;get IMR into AL
OR AL,01H ;mask out timer interrupt
PAUSE
OUT MSKREG,AL ;write mask to IMR
CLI ;Interrupts off during mod.
push bx
push es
savint cs:b$OldClkTic,timadr
pop es
pop bx
PUSH CS ;set [DS] = [CS]
POP DS
SETVEC TMRCTL,CLOCKTIC ;set clock interrupt
POP DS ;restore [DS]
POP DX
OR b$EventFlags,TimerInst ; set timer installed flag
IN AL,MSKREG ;get IMR into AL
AND AL,0FEH ;unmask timer interrupt
PAUSE
OUT MSKREG,AL ;write mask to IMR
POP AX ;restore [AX]
STI ;restore interrupts
cEnd
;***
;CLOCKTIC - The Timer Interupt vectors here AFTER updating the time-of-day.
;
; 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) or STRIG(2) Statement.
;
; NOTE: Rom clock interrupt routine saved [AX],[DX],[DS]
;
; read the comment at the top of the file for detail.
;******************************************************************************
cProc CLOCKTIC,<FAR>
cBegin
PUSH BP
PUSH DI
PUSH SI
PUSH DS
PUSH AX
MOV DS,CS:b$BASDSG ;Get DS addr for our vars.
TEST b$EventFlags,SLEEPtmr ; SLEEP timer on?
JZ NoWakeup ; brif not
DEC SleepCnt1 ; decrement low word of SLEEP timer
JNZ NoWakeup ; brif not timeout/wrap
DEC SleepCnt2 ; decrement high word of SLEEP timer
JNS NoWakeup ; brif not timeout
AND b$EventFlags,NOT (InSLEEP OR SLEEPtmr) ; break out of
; SLEEP wait loop
NoWakeup:
CMP TMENBL,1 ;is timer enabled?
JNZ TRYPEN ;Brif not
DEC TMCNT1 ;decrement timer count
JNZ TRYPEN ;Brif not zero
DEC TMCNT2 ;decrement the remaining byte
JNS TRYPEN ; Brif not negative
RESET:
MOV AX,TIMRN1 ;reset the timer
MOV TMCNT1,AX ;count after counting
MOV AX,TIMRN2 ; down the timer
MOV TMCNT2,AX ; it is word now
MOV TMRFLG,1 ;set timer event flag
MOV AL,TIMOFF ; AL = trap number for B$TrapEvent
CALL B$TrapEvent ;set global event flag
TRYPEN:
CMP LPEN.LPEN_ENABLE,0 ; PEN ON?
JE TICTRG ; No, Try Trigger
cCall B$PENINT ; Yes, Update Pen status.
TICTRG:
CALL b$pJoystInt ; process joystick interrupt (if present)
POP AX
POP DS
POP SI
POP DI
POP BP
JMP CS:b$OldClkTic ;go service the old interrupt 1C
cEnd nogen
;***
;SCTOIC -- translate number of seconds to number of interrupts
;
;Purpose:
; Converts the number of seconds to a factor as required by the operating
; system. Under DOS 2/3, we multiply [CL:DX] by 18.2 and return this number
; of clock ticks in [CX:DX]. Under DOS 5 we multiply [CL:DX] by 1000, and
; return this number of millesecodns in [CX:DX].
;
; DOS3 NOTE: .2(n)=n/5, IDIV is used here. Since max(n)=86400, the
; result will be a two-byte integer, and won't cause overflow.
;Entry:
; [CL:DX] = number of seconds
;
;Exit:
; [CX:DX] = number of interrupts needed
;
;Uses:
; AX.
;****
cProc SCTOIC,<NEAR>,<SI,DI>
cBegin
XOR CH,CH
MOV AX,DX
MOV DX,CX ; store n in [DX:AX] (for IDIV)
MOV DI,AX
MOV SI,DX ; save n in [SI:DI]
MOV CX,5 ; .2 is 1/5
IDIV CX ; get 0.2n in AX=[DX:AX]/[CX],
; and remainder is in DX
CMP DX,2 ; do we need to round ?
JNA NOADD1 ; Brif don't
INC AX ; increment one
NOADD1:
MOV DX,DI
MOV CX,SI ; one more n in [CX:DX]
CLC ; NC
RCL DX,1
RCL CX,1 ; [CX:DX]=2*n
PUSH CX ; save CX
MOV CX,4 ; loop count
MLOOP: ; multiple loop
CLC ; no carry
RCL DI,1 ; rotate left through carry
RCL SI,1
LOOP MLOOP ; when done, [SI:DI]=16*n
POP CX ; get back CX, so [CX|DX]=2*n
ADD DX,DI
ADC CX,SI ; [CX:DX]=18*n
ADD DX,AX
ADC CX,0 ; [CX:DX]=18.2 * n (nearly)
cEnd
;***
;B$SleepInit - set up timeout for SLEEP statement
;OEM-interface routine
;
;Purpose:
;
;Entry:
; [DX|AX] = number of seconds to wait
;Exit:
; [SleepCnt2|SleepCnt1] = number of clock ticks to wait
;Uses:
; Per convention
;Preserves:
;
;Exceptions:
; None.
;****
cProc B$SleepInit,<NEAR,PUBLIC>
cBegin
xchg AX,DX ; [CL|DX] = # of seconds
xchg AX,CX
call SCTOIC ; [CX|DX] = # of clock ticks
mov SleepCnt1,DX ; update counter variables
mov SleepCnt2,CX
cEnd
SUBTTL PLAY
PAGE
;***
;B$RDPLAY - play trapping and the PLAY function
;OEM-interface routine
;
;Purpose:
; This routine supports play trapping and the play function.
; A play event occurs when the background music queue shrinks
; from n to n-1 notes (where n is specified in the ON PLAY(n)
; statement). The event does not occur until PLAY trapping is
; enabled and the background music queue has length greater
; than n-1.
;
; When PLAY trapping is enabled and the music queue shrinks
; from n to n-1, the event flag and the play event flag are
; both set.
;
; See the documentation for B$POLLEV for a description of the
; event and trapping mechanisms.
;
;Entry:
; [AL] = Function code
; 0:Return [BX] = -1 if event occured since last
; call to B$RDPLAY with [AL] = 0
; 0 if event did not occur since
; last call to B$RDPLAY with [AL] = 0
; 1:Return [BX] = number of notes in the queue
; [AH] = Voice Id (multivoice only)
; 2:Set event threshold to [BX], the number of notes
; specified in the ON PLAY(n) statement
; 254: Enable PLAY trapping
; 255: Disable PLAY trapping
;
;Exit:
; [BX] = value if specified by function [AL]
; PSW.C set will cause a function call error
; to be declared
;
;Uses:
; Per convention
;
;Preserves:
; AX, CX, DX
;
;Exceptions:
; None.
;****
cProc B$RDPLAY,<NEAR,PUBLIC>,<SI,AX>
cBegin
CMP AL,0
JE CHKPLY ;check for play event
CMP AL,1
JE RTNOTE ;return # of notes in queue
CMP AL,2
JE STNOTE ;save # of notes in ON PLAY(n)
CMP AL,254
JE STPLAY ;enable play trapping
CMP AL,255
JE SPPLAY ;disable play trapping
STNOTE_ERROR:
STC ;set carry to indicate function
PlayExit:
cEnd ; restore registers & return
CHKPLY:
XOR BX,BX ; assume no event occured (BX = 0)
CMP b$PLENBL,0 ;is play trapping enabled?
JE RDPRET ; Brif not enabled
CMP b$PLAFLG,1 ;did play event occur?
JNE RDPRET ; Brif not
DEC BX ; return -1 in BX to report it
MOV b$PLAFLG,0 ;clear the play event flag
JMP SHORT RDPRET
RTNOTE:
MOV BX,OFFSET DGROUP:b$SNDQCB ; get the addr of sound-block
MOV BX,[BX].QUNOTE ; Get the remaining notes in queue
JMP SHORT RDPRET
STNOTE:
OR BX,BX ;test if zero
JZ STNOTE_ERROR ;if so, then error
CMP BX,32D ;test if greater than 32
JA STNOTE_ERROR ;if so, then error
MOV b$PLYCNT,BX ;store # of notes specified in
JMP SHORT RDPRET ;ON PLAY(n) statement in PLYCNT
STPLAY:
MOV b$PLENBL,1 ;enable trapping
JMP SHORT RDPRET
SPPLAY:
MOV b$PLENBL,0 ;disable trapping
RDPRET:
CLC ;clear carry to indicate no error
JMP SHORT PlayExit ; and return
;***
;B$PENINT -- PEN Update
;
; Called by Timer Interupt AFTER updating the
; time-of-day only if PEN or STRIG are ON.
;
; 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$PENINT,<NEAR>,<BX,CX,DX,SI>
cBegin
SCNIOS vReadLightPen ; Read Lpen
MOV SI,OFFSET DGROUP:LPEN ; Point to LPEN structure
; AH 01/00 if pen down/up
SAHF ; CF = 1/0 if pen down/up
SBB AX,AX ; AX = -1/0 if pen down/up
XCHG AH,[SI].LAND_FLAG ; Get old LAND_FLAG in AH and
; set it to new value
JZ PENINT_EXIT ; If pen not down nothing else to do
; Now, set the lpen-coords to new values as return by BIOS
ADD DX,0101H ; Make row/col 1-relative
MOV [SI].X_TOUCH,BX ; Update the TOUCH variables
MOV [SI].COL_TOUCH,DL ; Hi-Byte will always ramin zero
MOV [SI].ROW_TOUCH,DH ; --ditto--
MOV [SI].Y_TOUCH,CH ; --ditto--
CMP AH,AL ; Any change in the pen down status?
JE PENINT_EXIT ; Brif not
; Else, update the new LAND variables
MOV [SI].LPEN_STATUS,AL ; Set the current status as active
MOV [SI].Y_LAND,CH ; Hi-Byte will remain zero always
MOV [SI].COL_LAND,DL ; --ditto--
MOV [SI].ROW_LAND,DH ; --ditto--
MOV [SI].X_LAND,BX
MOV AL,PENOFF ; AL = trap number for B$TrapEvent
cCALL B$TrapEvent
PENINT_EXIT: ; Time to exit
cEnd ; End of B$PENINT
SUBTTL SIGNAL processing code
PAGE
sEnd EV_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -