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

📄 keyint3.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;
;	CW : Character Windows Drivers
;
;	keyint3.asm : DOS 3 key interrupt
;
;----------------------------------------------------------------------------

; Code space constants

staticD	lpsslBios,417H			;* BIOS shift state 0040:0017 !!!!

; Code space data!  Horrors!

staticD	pfnOldInt15,0			; old int 15 handler

;----------------------------------------------------------------------------

;********** EnableKeyboardKbd **********
;*	entry:	pinkb => INKB data
;*		fEnable => whether to enable or disable
;*		fExiting => exiting if !fEnable
;*	* enable or disable the keyboard handler
;*	exit : n/a

cProc	EnableKeyboardKbd, <FAR, PUBLIC, ATOMIC>, <DI>
    parmDP pinkb
    parmW  fEnable
    parmW  fExiting
cBegin	EnableKeyboardKbd

;*	* save pointer to INKB data
	mov	di,OFF_lpwDataKbd		;* Data in data segment
	mov	bx,pinkb
	mov	[di].pinkbCur,bx

	mov	ax,fEnable
	mov	[bx].fPollKeyboardInkb,ax	;* to poll or not to poll?
	or	ax,ax
	jnz	enable_keyboard

	jmp	disable_keyboard

enable_keyboard:
;*	* Enable the keyboard
	test	[di].fKeyboardEnabled,0ffh
	jz	enable_keyboard2
	jmp	end_enable_keyboard		;* already enabled

enable_keyboard2:
;*	* Initialize globals
;;	mov	[di].semCopyQueue,-1
	
	lea	ax,[di].rglKbBuffer
	mov	[di].queueKb+pStartQueue,ax
	mov	[di].queueKb+pHeadQueue,ax
	mov	[di].queueKb+pTailQueue,ax
	add	ax,clKbdBuff * 4		;* point to end
	mov	[di].queueKb+pEndQueue,ax
	mov	[di].queueKb+semQueue,-1	; initialize both semaphores

;*	* set globals to reflect initial state AND
;*	*  query to see if TSR is present
	mov	ax,tsrcInitTerm
	mov	[di].fKeyboardEnabled,al		;* enabled
	mov	bx,[di].pinkbCur
	mov	[bx].fKeyIsUpInkb,al			;* set up state

IFDEF WORDTSR
	;* Word protocal
	mov	ax,55FFh
	mov	bx,5
	xor	cx,cx
	int	16H
	xor	ax,4D53h
	jnz	@F
	mov	bx,[di].pinkbCur
	mov	[bx].fNormalKeyboardInkb,ax	;* 0 => proper TSR present
@@:
ELSE ;!WORDTSR
	;* Works (default) protocal
	lea	cx,[di].wTsrRepeat			;* DS:CX => two flags
	Assert	<verTsr EQ 0>
	xor	dx,dx
	mov	bx,drvOffset TsrRequest

	push	cs
	pop	es				;* es:bx => TsrRequest
	int	16H				;* nothing to return

	xor	ax,ackTsr			;* acknowledge ?
	mov	bx,[di].pinkbCur
	mov	[bx].fNormalKeyboardInkb,ax	;* 0 => proper TSR present
ENDIF ;!WORDTSR

;*	* Hook the INT 1B handler
	mov	al, 1Bh
	mov	bx, pfnOldInt1B		;* offset into KBD data
	mov	dx, drvOffset Int1BHandler
	cCall	Hooker

	mov	bx,[di].pinkbCur
	mov	cx,[bx].fNormalKeyboardInkb
	jcxz	end_enable_keyboard

;*	* Hook and initialize the INT 08 handler
	mov	al, 08h
	mov	bx, pfnOldInt08
	mov	dx, drvOffset Int08Handler
	cCall	Hooker

	mov	[di].rstCur, RST_IDLE
	mov	[di].ckeyRepeat, 0

;*	* Hook INT 16
	mov	al, 16h
	mov	bx, pfnOldInt16
	mov	dx, drvOffset Int16Handler
	cCall	Hooker
	mov	[di].fUnhook16, 0

;*	* Hook INT 9 (TSR not present)
	mov	al, 09h
	mov	bx, pfnOldInt09
	mov	dx, drvOffset Int09Handler
	cCall	Hooker

	call	HookInt15

	les	bx,lpsslBios
	mov	al,es:[bx]
	mov	[di].sslMirror,al
	mov	byte ptr [di].ssLastInt,al		;* set low byte only

;*	* check for extended (ronco) keyboard
	mov	[di].pmpscvwPlain,drvOffset mpscvwPlain
	mov	[di].pmpscvwShift,drvOffset mpscvwShift
IFNDEF	TANDY_1000	;* don't have to worry about this
	test	byte ptr es:[KbType],10H
	jz	not_ronco				;* not extended
	mov	bx,[di].pinkbCur
	cmp	[bx].fDisableExtendedInkb,0
	jne	not_ronco				;* not allowed
	mov	[di].Int16_CmdBase,10H
	mov	[di].pmpscvwPlain,drvOffset mpscvwPlainRonco
	mov	[di].pmpscvwShift,drvOffset mpscvwShiftRonco
ENDIF	; !TANDY_1000
not_ronco:



end_enable_keyboard:

cEnd	EnableKeyboardKbd

;*	* Disable keyboard *

disable_keyboard:
	test	[di].fKeyboardEnabled,0ffh
	jz	end_enable_keyboard
	mov	[di].fKeyboardEnabled,0

;*	* disable TSRs (even if they did not register with us)
IFDEF WORDTSR
	;* inform of departure
	mov	ax,55FFh
	mov	bx,5
	mov	cx,1
	int	16H
ELSE ;!WORDTSR
	mov	ax,tsrcInitTerm
	mov	dx,verTsrTerm			;* signal termination
	xor	bx,bx
	cmp	fExiting,0
	jne	exiting_forever
	inc	bx
exiting_forever:
	int	16H				;* nothing to return
ENDIF ;!WORDTSR

;*	* remove hooks
	push	ds
	mov	bx,[di].pinkbCur
	mov	cx,[bx].fNormalKeyboardInkb
	lds	dx,[di].pfnOldInt1B
	mov	ax,251BH
	int	21H

	jcxz	int9_not_hooked
	lds	dx,ss:[di].pfnOldInt08		;* get old int 08 handler
	mov	ax, 2508h
	int	21h

	lds	dx,ss:[di].pfnOldInt09		;* get old int 9 handler
	mov	ax,2509H
	int	21H

	lds	dx,ss:[di].pfnOldInt16
	mov	ax, 2516h
	int	21h

	cmp	ss:[di].fInt15_4F_Supported,0
	je	int15_not_hooked

	lds	dx,pfnOldInt15			;* get old int 15 handler
	mov	ax,2515H
	int	21H

int15_not_hooked:

int9_not_hooked:
	pop	ds
	jmp	short end_enable_keyboard


;----------------------------------------------------------------------------
;
; ::: Decide if we're going to hook int15 (to watch for int9 4F callback) :::
; 
; On the PS/2, it's risky to directly poll the keyboard with IN AL,60.
; The BIOS int9 provides a solution; it performs an int15 w/AH=4F and AL=
; the scan code.  An application can hook int15/4F and see the scan code
; without doing the direct polling.
;
; The only app we've seen that actually \required/ this was Word 4.0.  If
; you hold down the Alt key and roll the mouse around, Word 4.0 goes bongos.
; The int15/4F callback was implemented for Word 4.00A.
;
;;; We decided with Word 4.00A to only implement the callback with 
;;; DOS >= 3.30 but not 4.x.  This may be overly restrictive, but it 
;;; guarentees we catch all the PS/2s, which was the intent.
;
; We had decided the above.  But with MS-DOS 4.0 that changed, and we now
; implement for it also, meaning for all DOS >= 3.30.
;
; Note that if any TSR grabs int9 and does the IN AL,60, we're suspect to the
; same behaviour even if we're using the callback method.  The UB Network
; software is an example.

HookInt15:

	mov	ax,3000h
	mov	[di].fInt15_4F_Supported,al
	int	21h
	xchg	ah,al

	cmp	ax,031Eh		; If DOS < 3.30, then don't hook.
	jb	NoInt15

	mov	ax,0C000h
	int	15h			; Get system configuration parms.

	jc	NoInt15			; According to PS/2 BIOS TechRef:
	or	ah,ah			;   support    -> NC and AH == 0
	jnz	NoInt15			;   nonsupport -> CY and AH != 0

	test	byte ptr es:[bx+5],00010000b	; If kbd intercept sequence
	jz	NoInt15				; is alive, install our Int15

	mov	ax,3515h
	int	21h
	mov	word ptr pfnOldInt15,bx		; Should use CS override.
	mov	word ptr pfnOldInt15+2,es

	push	ds
	push	cs
	pop	ds
	mov	dx,drvOffset Int15Handler
	mov	ax,2515h
	int	21H
	pop	ds

	dec	[di].fInt15_4F_Supported
NoInt15:
	ret

;---------------------------------
; Hooker
;	Hooks an interrupt and saves the old handler's address in [DI].bx
;
;	entry:	AL = interrupt number
;		BX = kbd data offset of dword to contain old address
;		DX = drvOffset of new handler
;
cProc	Hooker, <NEAR, ATOMIC>
cBegin	Hooker

	AssertEQ di, OFF_lpwDataKbd

	push	dx
	push	ax
	push	bx

	mov	ah, 35h
	int	21h
	mov	ax, bx
	pop	bx
	add	bx, di
	mov	[bx], ax
	mov	[bx+2], es

	pop	ax
	mov	ah, 25h
	pop	dx
	push	ds
	push	cs
	pop	ds
	int	21h
	pop	ds

cEnd	Hooker

;----------------------------------------------------------------------------
;
;   TsrRequest
;
;	entry : AH = request code
;	* called by TSR programs to request action
;	exit : n/a (trashes normal registers)

cProc	TsrRequest, <FAR, ATOMIC>, <DS, DI>
cBegin	TsrRequest

	mov	cx,SEG_lpwDataKbd
	mov	ds,cx
	mov	di,OFF_lpwDataKbd		;* Data in data segment
	mov	bx,[di].pinkbCur
;*	* DS:DI => data, DS:BX => INKB

	cmp	ah,tsrrIgnoreAltUp
	jne	not_ignore_altup
	mov	[bx].fNonAltKeyHitInkb,1	;* => ignore next
not_ignore_altup:
	cmp	ah,tsrrAbort
	je	tsr_special_abort
end_tsr_request_poll:
;*	* after any request, poll the TSR
	mov	[bx].fPollKeyboardInkb,1
end_tsr_request_nopoll:

cEnd	TsrRequest


tsr_special_abort:
;*	* we have an escape key
	cCall	[bx].lpfnSpecialAbortInkb	;* call SpecialTsrAbort
	jmp	short end_tsr_request_nopoll

;----------------------------------------------------------------------------
;
; Int1BHandler()
;
; INT 1B is invoked when the ROM BIOS sees CTRL-BREAK.
; We hook this interrupt so that DOS never sees the CTRL-BREAK.
;
; Inputs:	none.
; Outputs:	none.
; Uses:		none, everything is saved.

Int1BHandler:
IFDEF KBD_CTRL_C_ABORT
	push	ds
	push	di
	push	ax
	mov	ax,SEG_lpwDataKbd
	mov	ds,ax
	mov	di,OFF_lpwDataKbd	;* Data in data segment
	mov	di,[di].pinkbCur	;* point to INKB
	mov	[di].fAbortInkb,1	;* Weird Abort (no message)
	pop	ax
	pop	di
	pop	ds
ENDIF
	iret


;----------------------------------------------------------------------------
;
;  InKey
;	entry : n/a
;	* Get an input key
;	exit : DX:AX = long value
;		DX = shift states
;		AH = scan code
;		AL = char
;		DS:DI => driver data
;	Note : a null character state is returned as AX==0

cProc	InKey,<PUBLIC,NEAR,ATOMIC>,<SI>
cBegin	InKey

	AssertEQ di,OFF_lpwDataKbd

	mov	bx,[di].pinkbCur
	mov	cx,[bx].fNormalKeyboardInkb
	jcxz	inkey_tsr

	xor	ax,ax
	cCall	LockRemoveQueue
	mov	dx,[di].ssCur
	jnz	end_inkey			; queue already locked
	mov	bx,[si].pHeadQueue
	cmp	bx,[si].pTailQueue
	jne	ik_readq
	cCall	FnzGetBiosKey
	jnz	ik_releaseq
	xor	ax,ax
	jmp	short ik_releaseq

ik_readq:
	mov	ax,[bx+0]
	mov	dx,[bx+2]
	cCall	IncQueuePtr
	mov	[si].pHeadQueue,bx

ik_releaseq:
	cCall	ReleaseRemoveQueue

end_inkey:

cEnd	InKey

inkey_tsr:
	xor	bx,bx
	mov	ax,tsrcInkey			;* special get key request
	int	16H				;* returns AH = sc, AL = char
						;* BX = ss
	mov	dx,bx
	jnz	end_inkey			;* got one (dx always valid)
	xor	ax,ax
	jmp	short end_inkey
	

;----------------------------------------------------------------------------


;********** FnzGetBiosKey **********
;*	entry : DS:DI => driver data
;*	* check for a bios character
;*	exit : z=> no key,
;*		else AX = char + scan code, DX = shift states
;*	TRASHES : AX/DX

cProc	FnzGetBiosKey, <NEAR>
cBegin	FnzGetBiosKey

	AssertEQ di,OFF_lpwDataKbd

	push	bx			;* Some TSRs clobber this
	push	cx			;* possibly this too

	mov	ah,[di].Int16_CmdBase	; Is there anything to get?
	inc	ah
	pushf
	call	[di].pfnOldInt16	; call the real BIOS, not our hook
	jz	end_bios_get_key	; nope return z

					; Liar!  Check again!

	mov	ah,[di].Int16_CmdBase	; Burn some time; get kbd flags.
	inc	ah
	inc	ah
	pushf
	call	[di].pfnOldInt16	; call the real BIOS, not our hook

	mov	ah,[di].Int16_CmdBase	; Is there anything to get?
	inc	ah
	pushf
	call	[di].pfnOldInt16	; call the real BIOS, not our hook
	jz	end_bios_get_key	; nope return z

	mov	ah,[di].Int16_CmdBase	; Get char + scan code
	pushf
	call	[di].pfnOldInt16

	mov	dx,[di].ssCur
	or	sp,sp			; set NZ flag, we got a key!

end_bios_get_key:
	pop	cx
	pop	bx
cEnd	FnzGetBiosKey


;----------------------------------------------------------------------------

Int15Handler:

	cmp	ah,4Fh
	jne	@F

	push	ax
	push	bx
	push	cx
	push	si
	push	di
	push	ds
	push	es

	mov	di,SEG_lpwDataKbd
	mov	ds,di
	mov	di,OFF_lpwDataKbd	; DS:DI -> Data in data segment
	mov	si,[di].pinkbCur	; DS:SI -> INKB data
	les	bx,lpsslBios		; ES:BX -> kbd data in low ram

	call	ScanCodeStuff		; al = the scan code.

	stc				; We don't want to eat the keystroke.

	pop	es
	pop	ds
	pop	di
	pop	si
	pop	cx
	pop	bx
	pop	ax

@@:
	jmp	[pfnOldInt15]

;----------------------------------------------------------------------------
;
;	The keyboard hardware interrupt handler

Int09Handler:

	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di
	push	ds
	push	es

	mov	di,SEG_lpwDataKbd
	mov	ds,di
	mov	di,OFF_lpwDataKbd	; DS:DI -> Data in data segment
	mov	si,[di].pinkbCur	; DS:SI -> INKB data
	les	bx,lpsslBios		; ES:BX -> kbd data in low ram

	cmp	[di].fInt15_4F_Supported,0
	jne	@F

	in	al,KbDataPort
	cCall	ScanCodeStuff			; Do the scan-code stuff.

@@:	mov	[di].fUnhook16, 1		; Give normal int16 to TSRs
	pushf
	call	[di].pfnOldInt09		; Daisy chain.
	mov	[di].fUnhook16, 0

; Restore anything we did to the BiosShiftState in ScanCodeStuff.

	test	[di].fShiftStateDiddled,0ffH
	jz	@F				; Jmp if not diddled
	mov	al,[di].sslMirror
	mov	es:[bx],al
	mov	[di].fShiftStateDiddled,0
@@:
	mov	al,es:[bx]
	mov	[di].sslMirror,al

ifdef KANJI
	mov	ah, 51h			; AX bios: get KANA shift status
	int	16h

	and	[di].ssCur, not SS_KANA
	test	ah, 00000010b		; test KANA bit
	jz	@F
	or	[di].ssCur, SS_KANA
@@:

⌨️ 快捷键说明

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