2639 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			2639 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;
 | |
| ;	Command & Conquer Red Alert(tm)
 | |
| ;	Copyright 2025 Electronic Arts Inc.
 | |
| ;
 | |
| ;	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 3 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, see <http://www.gnu.org/licenses/>.
 | |
| ;
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;**   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **
 | |
| ;***************************************************************************
 | |
| ;*                                                                         *
 | |
| ;*                 Project Name : Westwood 32 bit Library                  *
 | |
| ;*				  (Mouse Routines)
 | |
| ;*                                                                         *
 | |
| ;*                    File Name : KEYIREAL.ASM                             *
 | |
| ;*                                                                         *
 | |
| ;*                   Programmer : Philip W. Gorrow                         *
 | |
| ;*                                                                         *
 | |
| ;*                   Start Date : May 21, 1992                             *
 | |
| ;*                                                                         *
 | |
| ;*                  Last Update : July 13, 1994   [PWG]                    *
 | |
| ;*                                                                         *
 | |
| ;* This file sort of breaks the standard of keeping all of the keyboard    *
 | |
| ;* and mouse routines isolated.  This is done because the mouse and	   *
 | |
| ;* the keyboard share data, and the best way to do this is to put	   *
 | |
| ;* them in the same segment.  This should probably be split into several   *
 | |
| ;* include files to help make the code clearer once it is finally put	   *
 | |
| ;* together.								   *
 | |
| ;*                                                                         *
 | |
| ;*-------------------------------------------------------------------------*
 | |
| ;* Functions:                                                              *
 | |
| ;*   KeyNum_Translate -- Translates extended keynums to normal keynums	   *
 | |
| ;*   Stuff_Key_Word -- Stuffs a word of data into keyboard buffer          *
 | |
| ;*   Stuff_Key_Num -- Stuffs a key num code into the circular buffer       *
 | |
| ;*   Keystroke_Interrupt -- Real mode handler of input from the keyboard   *
 | |
| ;*   Break_Interrupt -- Handles the break key interrupt                    *
 | |
| ;*   Call_Interrupt_Chain -- Function PM calls to call RM interrupt chain  *
 | |
| ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
 | |
| ;*									   *
 | |
| ;*	Keyboard driver -- 8086 Assembly portion;			   *
 | |
| ;*	updated by: Phil Gorrow for 32 bit Protected Mode		   *
 | |
| ;***************************************************************************
 | |
| 
 | |
| ;---------------------------------------------------------------------------
 | |
| ; Set the assembly directives
 | |
| ;---------------------------------------------------------------------------
 | |
| IDEAL				; the product runs in ideal mode
 | |
| P386N				; use 386 real mode instructions
 | |
| MODEL TINY			; code must be tiny so it fits
 | |
| LOCALS ??			; ?? is the symbol for a local
 | |
| WARN				; generate all warnings we can
 | |
| JUMPS				; optimize jumps if possible
 | |
| 
 | |
| ;---------------------------------------------------------------------------
 | |
| ; Include all of the keyboard specific defines
 | |
| ;---------------------------------------------------------------------------
 | |
| INCLUDE "keyboard.inc"
 | |
| 
 | |
| CONDHIDE		EQU	08000H		; bit for testing conditional region
 | |
| CONDHIDDEN		EQU	04000H		; bit for testing conditional hidden
 | |
| RESTORE_VISIBLE_PAGE	EQU	0
 | |
| STORE_VISIBLE_PAGE	EQU	1
 | |
| 
 | |
| 
 | |
| GLOBAL	set_vesa_page 	:near
 | |
| GLOBAL	set_vesa_window :near
 | |
| GLOBAL	get_vesa_window :near
 | |
| GLOBAL	next_vesa_page	:near
 | |
| 
 | |
| ECHOON	equ 0
 | |
| ;---------------------------------------------------------------------------
 | |
| ; WARNING!!!!  All of the following code segment variables are shared by
 | |
| ;   the protected mode interrupt.  Do not change these unless you make the
 | |
| ;   proper changes to KEYSTRUC.INC.  If you do not know what you are doing,
 | |
| ;   find someone who does!!!
 | |
| ;---------------------------------------------------------------------------
 | |
| CODESEG
 | |
| 
 | |
| ;---------------------------------------------------------------------------
 | |
| ; Begin definition of Keyboard specific variables
 | |
| ;---------------------------------------------------------------------------
 | |
| SoundOn		DW	1	; toggled by alt S
 | |
| MusicOn		DW	1	; toggled by alt M
 | |
| KeyFlags	DD	REPEATON+CTRLALTTURBO	; all but repeat for now
 | |
| 
 | |
| 
 | |
| Break		DW	0
 | |
| 
 | |
| KeyMouseMove	DB	-1,0,1
 | |
| 		DB	-16,0,16
 | |
| 
 | |
| ScreenEdge	DW	320/2,0		; North
 | |
| 		DW	319,0		; North-East
 | |
| 		DW	319,138/2	; East
 | |
| 		DW	319,137		; South-East
 | |
| 		DW	320/2,137	; South
 | |
| 		DW	0,137		; South-West
 | |
| 		DW	0,138/2		; West
 | |
| 		DW	0,0		; North-West
 | |
| 		DW	320/2,138/2	; Center
 | |
| 
 | |
| 
 | |
| Bits		DB	01H,02H,04H,08H,10H,20H,40H,80H
 | |
| 
 | |
| CondPassKey	DW	0220H, 0320H, 060CH, 070DH, 066AH
 | |
| 		DW	0669H, 0230H, 0330H, 007DH, 017DH
 | |
| 		DW	025AH, 035AH, 0200H, 0410H, 046EH
 | |
| 		DW	026EH, 007CH
 | |
| 
 | |
| CondPassCond	DW	CTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO
 | |
| 		DW	CTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON
 | |
| 		DW	PAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE
 | |
| 		DW	TASKSWITCHABLE, BREAKON
 | |
| 
 | |
| EscRoutine	DD	0	; vector to execute on esc key press (0=none)
 | |
| 
 | |
| ; Extended raw keycodes to be converted to Westwood keycodes.
 | |
| ExtCodes	DB	038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H
 | |
| 		DB	051H,04DH,035H,01CH,037H
 | |
| 		DB	046H
 | |
| ; The matching Westwood keycodes.
 | |
| ExtNums		DB	62,  64,  75,  76,  79,  80,  81,  83,  84,  85
 | |
| 		DB	86,  89,  95, 108, 124,  0
 | |
| ; If extended mapping is disabled, then these codes really are...
 | |
| ExtRemap	DB	60,  58,  99, 104,  92,  91,  93,  96,  98, 101
 | |
| 		DB	103, 102, 55,  43, 124,  0
 | |
| ExtRemapEnd	DB	0
 | |
| 
 | |
| ExtKeyboard	DB	0	; flag for 101/102-key keyboard
 | |
| 
 | |
| 
 | |
| KeyBuffer	DW	128 DUP(0) ; set to empty
 | |
| KeyBufferHead	DD	0	; set to first entry
 | |
| KeyBufferTail	DD	0	; set to head for empty buffer
 | |
| KeyLock		DW	0	; num and caps lock bits
 | |
| KeyNums		DB	127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016
 | |
| 		DB	017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032
 | |
| 		DB	033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049
 | |
| 		DB	050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116
 | |
| 		DB	117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093
 | |
| 		DB	098,103,099,104,127,127,127,122,123
 | |
| 
 | |
| KeysCapsLock	DB	0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0
 | |
| KeysNumLock	DB	0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0
 | |
| KeysUpDown	DB	16 DUP(0) ; set to all keys up
 | |
| KeyStream	DB	16 DUP(0) ; set to all keys up
 | |
| PassCount	DW	0
 | |
| KeyStreamIndex	DW	0
 | |
| LastKeyE0	DB	0
 | |
| LastKeyE1	DB	0
 | |
| 
 | |
| ;
 | |
| ; Westwood key number values of keys to pass through
 | |
| ;
 | |
| ;			CAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT,
 | |
| ;			RIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN
 | |
| PassAlways	DB	30, 44, 57, 58, 60, 62, 64, 90, 128, 128
 | |
| PassAlwaysEnd	DB	128		; invalid code to END PassAlways
 | |
| CtrlFlags	DB	0
 | |
| 
 | |
| Buffer		DW	?
 | |
| Time		DW	?
 | |
| 
 | |
| ADJUST	= 1			; do not modify DRD
 | |
| 
 | |
| XYAdjust	DB	-ADJUST, -ADJUST	; 91 -> upleft
 | |
| 		DB	-ADJUST,  0		; 92 -> left
 | |
| 		DB	-ADJUST,  ADJUST	; 93 -> downleft
 | |
| 		DB	 0,  0			; 94 illegal
 | |
| 		DB	 0,  0			; 95 illegal
 | |
| 		DB	 0, -ADJUST		; 96 -> up
 | |
| 		DB	 0,  0			; 97 illegal (center)
 | |
| 		DB	 0,  ADJUST		; 98 -> down
 | |
| 		DB	 0,  0			; 99 illegal
 | |
| 		DB	 0,  0			; 100 illegal
 | |
| 		DB	 ADJUST, -ADJUST	; 101 -> upright
 | |
| 		DB	 ADJUST,  0		; 102 -> right
 | |
| 		DB	 ADJUST,  ADJUST	; 103 -> downright
 | |
| 	EdgeConv		DW	8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7
 | |
| 	MouseUpdate		DW	0
 | |
| 	MouseX			DW	0,0
 | |
| 	LocalMouseX		DW	0
 | |
| 	MouseY			DW	0,0
 | |
| 	LocalMouseY		DW	0
 | |
| 	IsExtKey		DB	0
 | |
| 	ExtIndex		DW	0
 | |
| 
 | |
| 	KeyOldRMI		DD	0			; The origianl RM interrupt seg:off.
 | |
| 	KeyOldPMIOffset		DD	0			; The origianl PM interrupt offset
 | |
| 	KeyOldPMISelector	DD	0			; The original PM interrupt segment.
 | |
| 
 | |
| 	KeyCodeOffset		DW	RM_Keystroke_Interrupt	; Offset of the code in the RM stuff.
 | |
| 	CallKeyRMIntOffset	DW	Call_Interrupt_Chain	; Offset of function to call DOS timer interrupt.
 | |
| 	CallKeyRMIntAddr	DD	0			; PM address of CallRealIntOffset for speed.
 | |
| 	PMIssuedKeyInt		DD	0
 | |
| 
 | |
| 	BrkOldRMI		DD	0			; The origianl RM interrupt seg:off.
 | |
| 	BrkOldPMIOffset		DD	0			; The origianl PM interrupt offset
 | |
| 	BrkOldPMISelector	DD	0			; The original PM interrupt segment.
 | |
| 
 | |
| 	BrkCodeOffset		DW	RM_Break_Interrupt	; Offset of the code in the RM stuff.
 | |
| 	CallBrkRMIntOffset	DW	0
 | |
| 	CallBrkRMIntAddr	DD	0			; PM address of CallRealIntOffset for speed.
 | |
| 	PMIssuedBrkInt		DD	0
 | |
| 	KeyIntDisabled		DD	0
 | |
| 
 | |
| 	DbgOldPMIOffset		DD	0	; The origianl PM interrupt offset
 | |
| 	DbgOldPMISelector	DD	0	; The original PM interrupt segment.
 | |
| 
 | |
| ;---------------------------------------------------------------------------
 | |
| ; Begin definition of Mouse Specific Variables for real mode
 | |
| ;---------------------------------------------------------------------------
 | |
| Button			DB	0	; current value of the mouse button
 | |
| MDisabled		DB	0	; Is the mouse driver disabled
 | |
| MInput			DB	1	; Defaults to mouse input allowed.
 | |
| Adjust			DW	0	; flag to adjust coordinates if necessary
 | |
| MouseStepX		DW	0	; step values if the mouse moves at
 | |
| MouseStepY		DW	0	;   more than one pixel at a time
 | |
| MouseOffsetX		DW	0	; Fractional step values used if a mouse
 | |
| MouseOffsetY		DW	0	;   moves at less than one pixel at a time
 | |
| MState			DW	0,0	; Tracks if mouse is hidden (TRUE) or not (FALSE)
 | |
| MouseXOld     		DW	0	; Holds last MouseX and MouseY to determine if
 | |
| MouseYOld     		DW	0	;   mouse needs to be redrawn
 | |
| MCState			DW	0	; Tracks if mouse conditional hidden (TRUE) or not
 | |
| MouseCXLeft		DW	0,0	; Conditional hide mouse left x position
 | |
| MouseCYUpper		DW	0,0	; Conditional hide mouse top y position
 | |
| MouseCXRight		DW	0,0	; Conditional hide mouse right x position
 | |
| MouseCYLower		DW	0,0	; Conditional hide mouse lower y position
 | |
| MouseCursor   		DD	0	; Pointer to the mouse cursor to draw
 | |
| MouseCursorSize		DW	0	; Pointer to buffer mouse is saved in
 | |
| MouseBuffer   		DD	0	; Pointer to buffer mouse is saved in
 | |
| MouseXHot     		DW	0,0	; Offset to mouse's x hot spot
 | |
| MouseYHot     		DW	0,0	; Offset to mouse's y hot spot
 | |
| MouseBuffX		DW	0,0	; X position background was saved at
 | |
| MouseBuffY		DW	0,0	; Y position background was saved at
 | |
| MouseBuffW		DW	0,0	; Width of the region saved for mouse
 | |
| MouseBuffH		DW	0,0	; Height of the region saved for mouse
 | |
| MouseWidth		DW	0,0	; Mouse cursor theoretical width
 | |
| MouseHeight		DW	0,0	; Mouse cursor theoretical height
 | |
| MouseCodeOffset		DW	RM_Mouse_Interrupt	; Offset of the code in the RM stuff.
 | |
| MouseRight		DW	0,0
 | |
| MouseBottom		DW	0,0
 | |
| 
 | |
| 
 | |
| ShadowPtr		dw	0
 | |
| DrawMousePtr 		dw	0
 | |
| 
 | |
| VGAMouseDraw		dw	VGA_Draw_Mouse
 | |
| VGAMouseShadow		dw	VGA_Mouse_Shadow_Buffer
 | |
| 
 | |
| VESAMouseDraw		dw	VESA_Draw_Mouse
 | |
| VESAMouseShadow		dw	VESA_Mouse_Shadow_Buffer
 | |
| 
 | |
| VesaPtr			dd	0
 | |
| banktable		dd      8 dup ( 0 )
 | |
| Adjust_XPos		dw 	0 , 0
 | |
| Adjust_YPos		dw 	0 , 0
 | |
| 
 | |
| 		align 2
 | |
| Keyboard_App_Stack_ES	dw 0		; This the System Stack Offsset
 | |
| Keyboard_App_Stack_SS	dw 0		; This the System Stack Selector
 | |
| Keyboard_StackPointer	dw 0DEADh	; We Create a Local Application
 | |
| Keyboard_Stack		dw 512 dup (0)
 | |
| Keyboard_StackStart	dw 0
 | |
| 
 | |
| Mouse_State		dw 0		; Mouse Temp Variable
 | |
| Mouse_Cond		dw 0		; Mouse Temp Variable
 | |
| Mouse_App_Stack_ES	dw 0		; This the System Stack Offsset
 | |
| Mouse_App_Stack_SS	dw 0		; This the System Stack Selector
 | |
| Mouse_StackPointer	dw 0DEADh	; We Create a Local Application
 | |
| Mouse_Stack		dw 512 dup (0)
 | |
| Mouse_StackStart	dw 0
 | |
| 
 | |
| 
 | |
| 
 | |
| current_page		dw	0
 | |
| ;***************************************************************************
 | |
| ;* KEYNUM_TRANSLATE -- Translates extended keynums to normal keynums	   *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	UWORD the keynum to translate				   *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:	WORD the translated keynum                                 *
 | |
| ;*                                                                         *
 | |
| ;* PROTO:	UWORD KeyNum_Translate(UWORD keynum);			   *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/11/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| 	GLOBAL	KeyNum_Translate:FAR
 | |
| 	PROC	KeyNum_Translate C FAR
 | |
| 	USES	cx,di,es,ds
 | |
| 	ARG	keycode:WORD
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 	mov	es,ax				; set es up for scansb
 | |
| 
 | |
| 	mov	ax,[keycode]
 | |
| 	test	[WORD PTR KeyFlags],TRACKEXT
 | |
| 	jne 	short ??fini
 | |
| 
 | |
| 	mov	cx,ExtRemap-ExtNums
 | |
| 	mov	di,OFFSET ExtNums
 | |
| 
 | |
| 	repne	scasb
 | |
| 	jcxz	short ??fini			; No match found.
 | |
| 
 | |
| 	mov	di,OFFSET ExtRemapEnd
 | |
| 	dec	di
 | |
| 	sub	di,cx
 | |
| 	mov	al,[es:di]
 | |
| ??fini:
 | |
| 	ret
 | |
| 	ENDP	KeyNum_Translate
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer            *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	WORD the code to stick into the circular buffer            *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room		   *
 | |
| ;*                                                                         *
 | |
| ;* PROTO:	VOID Stuff_Key_WORD(WORD code);				   *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/11/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| 	GLOBAL	C Stuff_Key_WORD:FAR
 | |
| 	PROC	Stuff_Key_WORD C FAR
 | |
| 	USES	si,bx,ds
 | |
| 	ARG	code:WORD
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	mov	ax,[WORD PTR KeyBufferTail]
 | |
| 	mov	si,ax
 | |
| 	add	ax,2
 | |
| 	and	ax,0FFh				; New KeyBufferTail value.
 | |
| 	cmp	[WORD PTR KeyBufferHead],ax
 | |
| 	je 	short ??noroom
 | |
| 
 | |
| 	mov	bx,[code]
 | |
| 	mov	[KeyBuffer+si],bx		; Record the keystroke.
 | |
| 	mov	[WORD PTR KeyBufferTail],ax
 | |
| 	xor	ax,ax
 | |
| 	ret
 | |
| 
 | |
| ??noroom:
 | |
| 	mov	ax,1
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	Stuff_Key_WORD
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer         *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	WORD the keycode to stuff                                  *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:      WORD !=0 is sucessful, ==0 is not enough room		   *
 | |
| ;*                                                                         *
 | |
| ;* PROTO:	VOID Stuff_Key_Num(WORD keynum);			   *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/11/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| 	GLOBAL	C Stuff_Key_Num:FAR
 | |
| 	PROC	Stuff_Key_Num C FAR
 | |
| 	USES	bx,cx,dx,di,si,ds
 | |
| 	ARG	keycode:WORD
 | |
| 	LOCAL	tail:WORD		; Original keybuffer tail (safety copy).
 | |
| 	LOCAL	size:WORD		; Size of write.
 | |
| 
 | |
| 	pushf
 | |
| 	cli				; disable interrupts
 | |
| 
 | |
| 	; Abort key recognition if in record mode and unable
 | |
| 	; to output key due to simultaneous DOS operation.
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 
 | |
| 	; Record the mouse position to be stuffed into buffer.
 | |
| 	mov	ax,[MouseX]
 | |
| 	mov	[LocalMouseX],ax
 | |
| 	mov	ax,[MouseY]
 | |
| 	mov	[LocalMouseY],ax
 | |
| 
 | |
| ??cando:
 | |
| 	mov	ax,[keycode]		; get the code
 | |
| 	or	ax,ax			; Null keycodes are not recorded.
 | |
| 	jne	short ??validkey
 | |
| 	jmp	??exit
 | |
| 
 | |
| 
 | |
| ??validkey:
 | |
| 
 | |
| 	test	[WORD PTR KeyFlags],KEYMOUSE	; is the numeric keypad moving the mouse?
 | |
| 	je	??no_pad_move
 | |
| 
 | |
| 	; ALT-cursor keys are undefined.  Pass them on to the program.
 | |
| 	test	ah,ALTPRESS		; is either alt key down?
 | |
| 	jne	??no_pad_move
 | |
| 
 | |
| 	test	[WORD PTR KeyFlags],SIMLBUTTON	; are we simulating left mouse presses
 | |
| 	je	short ??chkinsert
 | |
| 
 | |
| 	cmp	al,KN_RETURN
 | |
| 	je	short ??forceleft
 | |
| 
 | |
| 	cmp	al,KN_SPACE
 | |
| 	je	short ??forceleft
 | |
| 
 | |
| 	cmp	al,KN_KEYPAD_RETURN
 | |
| 	je	short ??forceleft
 | |
| 
 | |
| ??chkinsert:
 | |
| 	cmp	al,KN_INSERT
 | |
| 	jne	short ??regular
 | |
| 
 | |
| ??forceleft:
 | |
| 	mov	al,KN_LMOUSE
 | |
| 	or	[Button],1		; Left mouse bit.
 | |
| 	test	ah,KEYRELEASE
 | |
| 	je	??mousefake
 | |
| 	and	[Button],NOT 1
 | |
| 	jmp	??mousefake
 | |
| 
 | |
| ??regular:
 | |
| 	cmp	al,KN_DELETE
 | |
| 	jne	short ??regular2
 | |
| 	mov	al,KN_RMOUSE
 | |
| 	or	[Button],2		; Right mouse bit.
 | |
| 	test	ah,KEYRELEASE
 | |
| 	je	??mousefake
 | |
| 	and	[Button],NOT 2
 | |
| 	jmp	??mousefake
 | |
| 
 | |
| ??regular2:
 | |
| 	; DRD correction to ignore key releases for key mouse movement
 | |
| 	test	ah,KEYRELEASE
 | |
| 	jne	??no_pad_move
 | |
| 
 | |
| 	cmp	al,KN_CENTER
 | |
| 	je	short ??pad_move
 | |
| 	cmp	al,KN_UPLEFT		; less than upleft?
 | |
| 	jb	??no_pad_move		; yes, then it isn't a keypad key
 | |
| 	cmp	al,KN_DOWNRIGHT		; greater than downright?
 | |
| 	ja	??no_pad_move		; yes, then it isn't a keypad key
 | |
| 	cmp	al,KN_DOWNLEFT		; is it UPLEFT, LEFT, or DOWNLEFT?
 | |
| 	jbe	short ??pad_move
 | |
| 	cmp	al,KN_UPRIGHT		; is it UPRIGHT, RIGHT, or DOWNRIGHT?
 | |
| 	jae	short ??pad_move
 | |
| 	cmp	al,KN_UP		; up?
 | |
| 	je	short ??pad_move
 | |
| 	cmp	al,KN_DOWN		; down?
 | |
| 	jne	??no_pad_move
 | |
| 
 | |
| ??pad_move:
 | |
| 	; DRD correction to use ch for ah
 | |
| 	mov	ch,ah			; save shift-ctrl-alt-rlse status
 | |
| 
 | |
| 	xor	ah,ah			; get rid of any bits
 | |
| 	sub	al,KN_UPLEFT		; get a number between 0 and 12
 | |
| 	mov	bx,ax
 | |
| 	shl	bx,1			; double for WORD index
 | |
| 	add	bx,OFFSET XYAdjust
 | |
| 	mov	ax,[bx]			; get x,y add value
 | |
| 
 | |
| 	mov	bl,ah
 | |
| 	cbw
 | |
| 	xchg	ax,bx
 | |
| 	cbw
 | |
| 	xchg	ax,bx			; AX = mouse x delta, BX = mouse y delta
 | |
| 
 | |
| 	; DRD correction to use ch
 | |
| 	; The CTRL key moves the mouse to the edge of the screen.
 | |
| 	test	ch,CTRLPRESS		; is either ctrl key down?
 | |
| 	jne	short ??ctrlon		; if so, ctrl is on
 | |
| 
 | |
| 	; DRD correction to use ch
 | |
| 	; use fast speed of the mouse move if the shift key is held down.
 | |
| 	mov	dx,1			; for slow speed
 | |
| 	test	ch,SHIFTPRESS		; is either shift key down?
 | |
| 	je	short ??normspeed	; if not then neither shift is down
 | |
| ??doublespeed:
 | |
| 	add	dx,3			; for fast speed
 | |
| ??normspeed:
 | |
| 	add	bx,dx			; add speed for y index
 | |
| 	mov	bl,[KeyMouseMove+bx] 	; get speed for y delta
 | |
| 	xchg	ax,bx			; swap with ax to extend sign
 | |
| 	cbw
 | |
| 	xchg	ax,bx
 | |
| 	xchg	bx,dx			; save mouse y delta
 | |
| 	add	bx,ax			; add speed for x index
 | |
| 	mov	al,[KeyMouseMove+bx]	; get speed for x delta
 | |
| 	cbw
 | |
| 	xchg	bx,dx			; restore mouse y delta
 | |
| 
 | |
| 	jmp	short ??ctrloff
 | |
| 
 | |
| ??ctrlon:
 | |
| 
 | |
| 	; Table lookup method for determining hotkey positions for CTRL
 | |
| 	; cursor combination.  This algorithm is hard coded for an ADJUST
 | |
| 	; value of 3.  If this value changed, then this section will also
 | |
| 	; have to be modified.
 | |
| 	and	bx,011b			; Y = 1, 0, 3
 | |
| 	and	ax,011b			; X = 1, 0, 3
 | |
| 	; Table lookup method for determining hotkey positions for CTRL
 | |
| 	; cursor combination.  This algorithm is hard coded.
 | |
| 					;    -1, 0, 1
 | |
| 	and	bx,011b			; Y = 3, 0, 1
 | |
| 	and	ax,011b			; X = 3, 0, 1
 | |
| 	shl	bx,1
 | |
| 	shl	bx,1
 | |
| 	or	bx,ax			; Lookup index.
 | |
| 
 | |
| 	; Convert raw index into logical (clockwise) index.
 | |
| 	shl	bx,1
 | |
| 	mov	bx,[EdgeConv+bx]
 | |
| 	shl	bx,1
 | |
| 	shl	bx,1
 | |
| 	mov	ax,[ScreenEdge+bx]	; New absolute X
 | |
| 	mov	bx,[ScreenEdge+bx+2] ; New absolute Y
 | |
| 	mov	[LocalMouseX],ax
 | |
| 	mov	[LocalMouseY],bx
 | |
| 
 | |
| ??set_xyz:
 | |
| 	mov	ax,[LocalMouseX]	; get new mouse x,y
 | |
| 	mov	bx,[LocalMouseY]
 | |
| 	jmp	short ??set_xy
 | |
| 
 | |
| 	; Process a normal faked mouse move.
 | |
| ??ctrloff:
 | |
| 	; DRD change
 | |
| 	add	[LocalMouseX],ax	; save it in our local
 | |
| 	jns	short ??not_negative_x
 | |
| 	xor	ax,ax
 | |
| 	mov	[LocalMouseX],ax	; clear our local
 | |
| 
 | |
| ??not_negative_x:
 | |
| ; DRD change
 | |
| 	add	[LocalMouseY],bx	; save it in our local
 | |
| 	jns	short ??not_negative_y
 | |
| 	xor	bx,bx
 | |
| 	mov	[LocalMouseY],bx	; clear our local
 | |
| 
 | |
| ??not_negative_y:
 | |
| 	mov	ax,[LocalMouseX]	; get new mouse x,y
 | |
| 	mov	bx,[LocalMouseY]
 | |
| 	cmp	ax,MAX_X_PIXEL		; bigger than
 | |
| 	jle	short ??check_y
 | |
| 	mov	ax,MAX_X_PIXEL
 | |
| 
 | |
| ??check_y:
 | |
| 	cmp	bx,MAX_Y_PIXEL		; bigger than
 | |
| 	jle	short ??set_xy
 | |
| 	mov	bx,MAX_Y_PIXEL
 | |
| 
 | |
| ??set_xy:
 | |
| 	mov	[LocalMouseX],ax
 | |
| 	mov	[LocalMouseY],bx
 | |
| 	mov	[MouseX],ax
 | |
| 	mov	[MouseY],bx
 | |
| 	cmp	[MouseUpdate],0	; wait until mouse interrupt is done
 | |
| 	jne	short ??noshow
 | |
| 
 | |
| 	call	Low_Hide_Mouse
 | |
| 	call	Low_Show_Mouse
 | |
| ??noshow:
 | |
| 	mov	ax,KN_MOUSE_MOVE
 | |
| ??mousefake:
 | |
| 	mov	[keycode],ax		; Fake a MOUSE_MOVE event.
 | |
| 
 | |
| ??no_pad_move:
 | |
| 	; Fetch working pointers to the keyboard ends.
 | |
| 	mov	si,[WORD KeyBufferTail]
 | |
| 	mov	[tail],si		; Safety record.
 | |
| 	mov	di,[WORD PTR KeyBufferHead]
 | |
| 
 | |
| 	; Record the base keycode (if there is room).
 | |
| 	push	ax
 | |
| 	call	Stuff_Key_WORD
 | |
| 	add	sp,2
 | |
| 	or	ax,ax
 | |
| 	jne	short ??jmpnoroom
 | |
| 
 | |
| 	; Also record the mouse coordinates if necessary.
 | |
| 	mov	ax,[keycode]		; get key code
 | |
| 	cmp	al,KN_MOUSE_MOVE	; mouse move?
 | |
| 	je	short ??recordmouse	; yes? then record the mouse cooordinates
 | |
| 	cmp	al,KN_LMOUSE
 | |
| 	je	short ??recordmouse
 | |
| 	cmp	al,KN_RMOUSE
 | |
| 	je	short ??recordmouse
 | |
| 	jmp	short ??ok
 | |
| ??jmpnoroom:
 | |
| 	jmp	??noroom
 | |
| 
 | |
| 	; Record mouse coordinate X.
 | |
| ??recordmouse:
 | |
| 	push	[LocalMouseX]
 | |
| 	call	Stuff_Key_WORD
 | |
| 	add	sp,2
 | |
| 	or	ax,ax
 | |
| 	jne	??jmpnoroom
 | |
| 	add	[size],2
 | |
| 
 | |
| 	; Record mouse coordinate Y.
 | |
| 	push	[LocalMouseY]
 | |
| 	call	Stuff_Key_WORD
 | |
| 	add	sp,2
 | |
| 	or	ax,ax
 | |
| 	jne	??jmpnoroom
 | |
| 	add	[size],2
 | |
| 
 | |
| ??ok:
 | |
| 	; If PASSBREAKS is not active and this is a keyboard
 | |
| 	; break AND it is not a mouse event, then don't put
 | |
| 	; it into the buffer.
 | |
| 	mov	bx,0101h		; Bit control tools.
 | |
| 	mov	ax,[keycode]
 | |
| 	cmp	al,KN_MOUSE_MOVE
 | |
| 	je 	short ??notreal
 | |
| 	cmp	al,127
 | |
| 	je	short ??notreal
 | |
| 	test	ah,KEYRELEASE
 | |
| 	je	short ??real
 | |
| 	xor	bl,bl
 | |
| 	test	[WORD PTR KeyFlags],PASSBREAKS
 | |
| 	jne 	short ??real
 | |
| 	cmp	al,KN_LMOUSE
 | |
| 	je 	short ??real
 | |
| 	cmp	al,KN_RMOUSE
 | |
| 	je 	short ??real
 | |
| ??notreal:
 | |
| 	mov	[WORD PTR KeyBufferTail],si	; Nullify any KeyBufferTail changes.
 | |
| ??real:
 | |
| 
 | |
| 	; Update the KeysUpDown bit array.
 | |
| 	mov	di,ax
 | |
| 	and	di,07Fh
 | |
| 	mov	cl,3
 | |
| 	shr	di,cl			; DI = Byte offset into bit table.
 | |
| 	mov	cl,al
 | |
| 	and	cl,0111b		; CL = Bit offset into bit table byte.
 | |
| 	shl	bx,cl
 | |
| 	not	bh
 | |
| 
 | |
| 	; If this is a reapeat key and the key is already being held
 | |
| 	; down, then don't stuff it into the keyboard buffer.
 | |
| 	test	bl,[KeysUpDown+di]
 | |
| 	je	short ??notalready
 | |
| 	test	[WORD PTR KeyFlags],REPEATON
 | |
| 	jne	short ??notalready
 | |
| 	mov	[WORD PTR KeyBufferTail],si	; Nullify any KeyBufferTail changes.
 | |
| ??notalready:
 | |
| 	and	[KeysUpDown+di],bh	; Force key bit to zero.
 | |
| 	or	[KeysUpDown+di],bl	; Insert key bit as appropriate.
 | |
| ;??notreal:
 | |
| 
 | |
| 	; Successful keybuffer stuff could result in a
 | |
| ??norecord:
 | |
| 	mov	ax,1
 | |
| 	jmp short ??exit
 | |
| 
 | |
| 	; Unsuccessful keybuffer stuff.
 | |
| ??noroom:
 | |
| 	mov	ax,[tail]
 | |
| 	mov	[WORD PTR KeyBufferTail],ax
 | |
| 	xor	ax,ax			; Signal an error.
 | |
| 
 | |
| ??exit:
 | |
| 	popf
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	Stuff_Key_Num
 | |
| ;***********************************************************
 | |
| 
 | |
| 
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* KEYSTROKE_INTERRUPT -- Handles input that comes from the keyboard       *
 | |
| ;*                                                                         *
 | |
| ;* This routine intercepts the key codes on their way to the		   *
 | |
| ;* BIOS.  With the adjustment of the Flags described above		   *
 | |
| ;* you can get a wide variety of effects.				   *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:      none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* WARNINGS:    This is an interrupt function                              *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/13/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| label RM_Keystroke_Interrupt
 | |
| 	GLOBAL	C Keystroke_Interrupt:FAR
 | |
| 	PROC	Keystroke_Interrupt C FAR
 | |
| 
 | |
| IF 0
 | |
| 	push	ax
 | |
| 	inc	ax
 | |
| 	pop	ax
 | |
| 	iret
 | |
| 
 | |
| ELSE
 | |
| 	push	ax
 | |
| 	push	bx
 | |
| 	push	cx
 | |
| 	push	di
 | |
| 	push	ds
 | |
| 	push	dx
 | |
| 	push	es
 | |
| 	push	si
 | |
| 	cld
 | |
| 
 | |
| 	mov	ax,cs			; set ds to cs to avoid cs overide
 | |
| 	mov	ds,ax
 | |
| 
 | |
| 	; At this point we do not know if the SS selector is a
 | |
|  	; System Stack or the Application Stack pointer.
 | |
| 	; Soo to be in the safe side we create our own local
 | |
| 	; Stack Pointer	Selector Relative to DS
 | |
| 	; Note Do not try this trick in a reentrant interrupt
 | |
| 	mov cx, ss				; get SS
 | |
| 	mov [Keyboard_App_Stack_ES], sp		; Protect ES
 | |
| 	mov [Keyboard_App_Stack_SS], cx		; Protect SS
 | |
| 	lea dx, [Keyboard_StackStart ]		; Compute Local Stack size
 | |
| 	and dx, -2;
 | |
| 	cli					; Disable All interrupts
 | |
| 	mov ss, ax				; Set new SS Selector
 | |
| 	mov sp, dx				; Set new Stack Offset
 | |
| 	sti					; Enable Interrupts
 | |
| 
 | |
| 	cmp	[WORD PTR PMIssuedKeyInt],0; Check to see if PM made Int call.
 | |
| 	mov	[WORD PTR PMIssuedKeyInt],0; Make it false.
 | |
| 	jne	??passcode	; if so, just call Int Chain.
 | |
| 
 | |
| 
 | |
| 	mov	dx,[WORD PTR KeyFlags]
 | |
| 	;*** The following fix allows proper caps and num lock tracking on Tandy
 | |
| 	; 10-6-89 LJC, DRD
 | |
| 
 | |
| 	and	[KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive
 | |
| 	mov	ax,040H			; BIOS segment
 | |
| 	mov	es,ax			; put in es
 | |
| 	test	[BYTE PTR es:017H],040H	; test Caps lock bit in BIOS
 | |
| 	je	short ??bioscapsoff	; skip activate code
 | |
| 	or	[KeyLock],CAPSLOCK	; Caps Lock active
 | |
| 
 | |
| ??bioscapsoff:
 | |
| 	test	[BYTE PTR es:017H],020H	; test Num lock bit in BIOS
 | |
| 	je	short ??biosnumoff	; skip activate code
 | |
| 	or	[KeyLock],NUMLOCK 	; Num Lock active
 | |
| 
 | |
| ??biosnumoff:
 | |
| 	mov	[ExtKeyboard],TRUE 	; assume 101/102-key keyboard
 | |
| 	test	[BYTE PTR es:096H],010H	; test for 101/102-key keyboard
 | |
| 	jne	short ??extkeyboard	; skip deactivate code
 | |
| 	mov	[ExtKeyboard],FALSE 	; no 101/102-key keyboard
 | |
| 
 | |
| ??extkeyboard:
 | |
| 	mov	ax,cs			; set ds to cs to avoid cs overide
 | |
| 	mov	es,ax
 | |
| 
 | |
| 	cld				; clear direction flag for strings
 | |
| 	xor	ah,ah			; clear ctrl flags to 0
 | |
| 	mov	bx,0101H		; set key to a make by default
 | |
| 	in	al,KEYDATA		; get a code from the keyboard
 | |
| 
 | |
| 	;
 | |
| 	; New CODE to montior key stream
 | |
| 	;
 | |
| 	mov	bx,[KeyStreamIndex]
 | |
| 	mov	[KeyStream+bx],al
 | |
| 	inc	bx
 | |
| 	and	bx,15
 | |
| 	mov	[KeyStreamIndex],bx
 | |
| 	mov	bx,0101H		; set key to a make by default
 | |
| 	;
 | |
| 	; END OF SEQUENCE
 | |
| 	;
 | |
| 
 | |
| 	;
 | |
| 	; Handle the PAUSE key being pressed.  If it is pressed, then
 | |
| 	; signal that the next two input codes are to be thrown out.
 | |
| 	;
 | |
| 	cmp	al,0E1H			; see if this is a pause/break
 | |
| 	jne	short ??notpcode	; not a pause/break start code
 | |
| 	mov	[LastKeyE1],3		; absorb this and next two codes
 | |
| 
 | |
| ??notpcode:
 | |
| 	cmp	[LastKeyE1],0		; are we in a pause/break code
 | |
| 	je	short ??notpause	; no, just keep going
 | |
| 	dec	[LastKeyE1]		; yes, dec the count
 | |
| 	test	dx,PAUSEON		; should it pass these codes
 | |
| 	jne 	??passcode		; pass the code
 | |
| 	jmp	??absorbcode		; don't pass code
 | |
| 
 | |
| ??notpause:
 | |
| 	;
 | |
| 	; Record any extended key codes that arrive.  They will be
 | |
| 	; taken into account with the next code.
 | |
| 	;
 | |
| 	cmp	al,0E0H			; is it an extended code
 | |
| 	jne	short ??notextcode	; if not skip to handle key
 | |
| 	mov	[LastKeyE0],TRUE	; set the extended code to 1
 | |
| ??jmppasscode:
 | |
| 	jmp	??passcode		; always pass E0s
 | |
| 
 | |
| ??notextcode:
 | |
| 
 | |
| 	;
 | |
| 	; Check and acknowledge if the key is a make or a break.
 | |
| 	;
 | |
| 	test	al,080H			; test for high bit
 | |
| 	je	short ??make		; if off its a make
 | |
| 	xor	bl,bl			; set make/break to break
 | |
| 	and	al,07FH			; clear high bit
 | |
| 	or	ah,KEYRELEASE		; CDY NEW -- ABSENT IN OLD CODE
 | |
| 
 | |
| ??make:
 | |
| 	;
 | |
| 	; Translate the raw keycode into the Westwood keycode.
 | |
| 	;
 | |
| 	cmp	[LastKeyE0],FALSE	; was the prev byte an E0?
 | |
| 	je 	short ??normal		; if not it is a normal key
 | |
| 	mov	[LastKeyE0],FALSE	; if so clear for next read
 | |
| 	mov	[IsExtKey],TRUE	; it is an extended key
 | |
| 	mov	di,OFFSET ExtCodes	; get offset of extended codes table
 | |
| 	mov	cx,(ExtNums-ExtCodes)	; get number of entrys in ext table
 | |
| 	repne	scasb			; look for a match
 | |
| 	jcxz	??absorbcode		; Not recognized, so throw it away.
 | |
| 	mov	al,[(ExtNums - ExtCodes) - 1 + di] ; get the match
 | |
| 	mov	[IsExtKey],FALSE	; it is not an extended key
 | |
| 	jmp 	short ??notext
 | |
| 
 | |
| ??normal:
 | |
| 	cmp	al,07Ah
 | |
| 	jne	short ??normok
 | |
| 	mov	al,128
 | |
| 	jmp	short ??notext
 | |
| ??normok:
 | |
| 	mov	di,ax			; use code as an index
 | |
| 	and	di,007Fh		; Mask off any release bit.
 | |
| 	mov	al,[KeyNums+di]		; get the key number of this key
 | |
| 
 | |
| ??notext:
 | |
| 	;
 | |
| 	; Test and set the CTRL bit.
 | |
| 	;
 | |
| 	test	[KeysUpDown+8],001H	; is the right ctrl down?
 | |
| 	jne	short ??ctrlon		; if so, ctrl is on
 | |
| 	test	[KeysUpDown+7],004H	; is the left ctrl down?
 | |
| 	je	short ??ctrloff		; if not, neither are down, no ctrl
 | |
| 
 | |
| 	; DRD
 | |
| 	; check for CTRL-NUMLOCK for pause on some keyboards
 | |
| 
 | |
| 	cmp	al,KN_NUMLOCK		; check for CTRL-NUMLOCK
 | |
| 	jne	short ??ctrlon
 | |
| 
 | |
| 	cmp	[ExtKeyboard],TRUE	; if 101/102-key keyboard it is ok
 | |
| 	je	short ??ctrlon
 | |
| 
 | |
| 	test	dx,PAUSEON		; should it pass these codes
 | |
| 	jne	short ??ctrlon		; pass the code
 | |
| 
 | |
| 	jmp	??absorbcode		; don't pass code
 | |
| 
 | |
| ??ctrlon:
 | |
| 	or	ah,CTRLPRESS		; or on the ctrl bit in flags
 | |
| 
 | |
| ??ctrloff:
 | |
| 	;
 | |
| 	; Test and set the ALT bit.
 | |
| 	;
 | |
| 	test	[KeysUpDown + 7],050H	; is either alt key down?
 | |
| 	je	short ??altoff
 | |
| 	or	ah,ALTPRESS		; or on the alt bit in flags
 | |
| 
 | |
| ??altoff:
 | |
| 	;
 | |
| 	; Remap the keyboard keys if this is requested. (Do not set DGROUP
 | |
| 	;   as it is unecessary)
 | |
| 	push	ax
 | |
| 	call	KeyNum_Translate
 | |
| 	add	sp,2
 | |
| 
 | |
| ;------	Set the shift bit if necessary.
 | |
| 	test	[KeysUpDown+5],010H	; is the left shift down?
 | |
| 	jne	short ??shifton		; if so the shift is on
 | |
| 	test	[KeysUpDown+7],002H	; is the right shift down?
 | |
| 	je	short ??shiftoff	; if not then neither shift is down
 | |
| 
 | |
| ??shifton:
 | |
| 	or	ah,SHIFTPRESS		; or on the shift bit in flags
 | |
| 
 | |
| ??shiftoff:
 | |
| 	;
 | |
| 	;------	Toggle the shift state if the caps lock key is on (if necessary).
 | |
| 	;
 | |
| 	mov	di,ax
 | |
| 	and	di,07Fh
 | |
| 	shr	di,1
 | |
| 	shr	di,1
 | |
| 	shr	di,1
 | |
| 	mov	bx,ax
 | |
| 	and	bx,07Fh
 | |
| 	and	bl,0111b
 | |
| 	mov	ch,[Bits+bx]		; get the bit to test
 | |
| 	test	[KeyLock],CAPSLOCK	; is the caps lock on?
 | |
| 	je	short ??capsoff		; if not don't worry about it
 | |
| 	test	ch,[KeysCapsLock+di]	; get code for keycaps
 | |
| 	je	short ??capsoff		; its not effected
 | |
| 	xor	ah,SHIFTPRESS		; toggle the shift flag
 | |
| 
 | |
| ??capsoff:
 | |
| 	;
 | |
| 	;------	Toggle the shift state if the num-lock key is on (if necessary).
 | |
| 	;
 | |
| 	test	[KeyLock],NUMLOCK	; is the num lock key on?
 | |
| 	je	short ??numlockoff	; if not don't worry about it
 | |
| 	test	ch,[KeysNumLock+di]	; get code for numlock
 | |
| 	je	short ??numlockoff	; if not effected skip toggle
 | |
| 	xor	ah,SHIFTPRESS		; toggle the shift flag if effected
 | |
| 
 | |
| ??numlockoff:
 | |
| ;------ Remember the current control/shift/alt bit settings for later use.
 | |
| 
 | |
| ;??noshiftever:
 | |
| 	mov	[CtrlFlags],ah		; save off shift-ctrl-alt flags
 | |
| 					; for the mouse and joystick routines
 | |
| 					; to use in stuffing key into the
 | |
| 					; keyboard buffer.
 | |
| 	test	dx,DEBUGINT
 | |
| 	jz	??not_toggle
 | |
| 
 | |
| 
 | |
| IF DEBUG
 | |
| 	cmp	[KeyIntDisabled],1
 | |
| 	jne	??not_currently_disabled
 | |
| 	cmp	ax,115			; is it the F4 key
 | |
| 	je	??disable
 | |
| 	cmp	ax,118			; is it less then F7 key
 | |
| 	jb	??justpass
 | |
| 	cmp	ax,120			; is it greater than F9 key
 | |
| 	ja	??justpass
 | |
| ??disable:
 | |
| 	mov	[KeyIntDisabled],0
 | |
| ??justpass:
 | |
| 	jmp	??passcode
 | |
| 
 | |
| ??not_currently_disabled:
 | |
| 	cmp	ax,125
 | |
| 	jne	??not_toggle
 | |
| 	mov	[KeyIntDisabled],1
 | |
| 	jmp	??absorbcode
 | |
| ENDIF
 | |
| 
 | |
| ??not_toggle:
 | |
| 
 | |
| ;------	The CTRL-ALT-DEL key combination always gets passed to the system.
 | |
| 	cmp	ax,0668H		; is it ctrl alt del?
 | |
| 	je	??passcode
 | |
| 	cmp	ax,064CH		; is it ctrl alt ext del?
 | |
| 	je	??passcode	; if so don't add it to the buffer
 | |
| 
 | |
| ;------ Special Ctrl-C check.
 | |
| 	cmp	ax,0230h
 | |
| 	je	short ??breaker
 | |
| 	cmp	ax,027Eh
 | |
| 	jne	short ??nobreak
 | |
| ??breaker:
 | |
| 	mov	[Break],1
 | |
| 
 | |
| ??nobreak:
 | |
| ;------	Check for Music and Sound control keys.
 | |
| 	cmp	ax,0420H		; is this an alt s
 | |
| 	jne	short ??checkmusic	; toggle the Sound variable
 | |
| 	push	ax
 | |
| 	mov	ax,[SoundOn]
 | |
| 	xor	ax,01H
 | |
| 	push	ax
 | |
| 	add	sp,2
 | |
| 	pop	ax
 | |
| 
 | |
| ??checkmusic:
 | |
| 	cmp	ax,0434H		; is this an alt m
 | |
| 	jne	short ??esc		; toggle the Music variable
 | |
| 	push	ax
 | |
| 	mov	ax,[MusicOn]
 | |
| 	xor	ax,01H
 | |
| 	push	ax
 | |
| 	add	sp,2
 | |
| 	pop	ax
 | |
| 
 | |
| ??esc:
 | |
| 
 | |
| 	push	ax
 | |
| 	call	Stuff_Key_Num
 | |
| 	pop	ax
 | |
| ??skipstuff:
 | |
| 
 | |
| ;------	Do the special ESC routine if necessary.
 | |
| 	cmp	al,110			; is this the esc key?
 | |
| 	jne	short ??noroutine	; if not goto the pass always
 | |
| 	cmp	[WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump
 | |
| 	je	short ??noroutine
 | |
| 	push	ax
 | |
| 	call	[EscRoutine]
 | |
| 	pop	ax
 | |
| 
 | |
| ??noroutine:
 | |
| ;------	Check to see if the key is to be passed to the system or not.
 | |
| 	mov	di,OFFSET PassAlways	; get offset to table
 | |
| 	mov	cx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1
 | |
| 	repne	scasb			; look for a match
 | |
| 	or	cx,cx			; see if there was no match
 | |
| 	jne	??passcode	; CDY JLB 7/11 optimization
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| ??passalways:
 | |
| 	; now check for conditional passes
 | |
| 	mov	di,OFFSET CondPassKey	; get offset to cond key table
 | |
| 	mov	cx,(CondPassCond-CondPassKey) ; get number of entries
 | |
| 	shr	cx,1			; cut in half for words
 | |
| 	repne	scasw			; look for a match
 | |
| 	jcxz	short ??notcondpass	; OPTIMIZATION CDY JLB
 | |
| 	mov	bx,[(CondPassCond - CondPassKey) - 2 + di]
 | |
| 	and	bx,dx			; are the conditions met?
 | |
| 	je	short ??notcondpass	; NO... check normally.
 | |
| 	jmp	short ??passcode	; YES... pass back to system.
 | |
| ;
 | |
| ;------	Last check before passing keycode back to the system.
 | |
| ;
 | |
| ??notcondpass:
 | |
| 	test	dx,FILTERONLY		; is the filter only flag on?
 | |
| 	je	short ??absorbcode	; if not, absorb the code.
 | |
| 
 | |
| ??passcode:
 | |
| 
 | |
| 	inc	[cs:PassCount]
 | |
| 
 | |
| ;mov   ax , 0B000h
 | |
| ;mov   es, ax
 | |
| ;inc   [BYTE PTR es : 40h]
 | |
| 
 | |
| 	; Now it is time to set up for the call to the System Keyboard
 | |
| 	; interrupt handler.
 | |
| 	; 1 -Restore System Stack Pointer Selector before exit Interrupt
 | |
| 	; 2- We Create a Returning Point from Interrupt by Push A
 | |
|  	;    Interupt Stack Frame into the Stack Pointer
 | |
| 	; 3- We make a Far jump to the interuupt handler
 | |
| 	cmp [Keyboard_StackPointer],0DEADh
 | |
| 	je  ??stackok
 | |
| 	push cx
 | |
| 	push di
 | |
| 	push ax
 | |
| 	push es
 | |
| 	mov  ax,0A000h
 | |
| 	mov  es,ax
 | |
| 	xor  di,di
 | |
| 	mov  cx,64000
 | |
| 	mov  ax,1
 | |
| 	rep  stosb
 | |
| 	pop  es
 | |
| 	pop  ax
 | |
| 	pop  di
 | |
| 	pop  cx
 | |
| ??stackok:
 | |
| 	cli				       ; disable Interrupts
 | |
| 	mov dx, [Keyboard_App_Stack_SS]
 | |
| 	mov ss, dx			       ; Get System Stack Selector
 | |
| 	mov sp, [Keyboard_App_Stack_ES]      ; Get System Stack offset
 | |
| 	sti				       ; Enable Interrupts
 | |
| 
 | |
| 	lea	dx, [??Call_Back_Keyboard]   ; Get Return address offset
 | |
|  	pushf				      ; push flags
 | |
| 	push	cs			      ; push Code segment
 | |
| 	push	dx			      ; push Offset
 | |
| 
 | |
| 	; Now we need to simulate an interrup call by using ired
 | |
| 	; because we still want to come back here from the
 | |
| 	; Old Keyboard interrupt handle.
 | |
| 	pushf
 | |
| 	push	[word ptr KeyOldRMI + 2] 	; push orig segment.
 | |
| 	push    [word ptr KeyOldRMI]   		; push orig offset.
 | |
| 	iret	 		        	; call interrupt
 | |
| 
 | |
| ??absorbcode:
 | |
| 
 | |
| ;mov   ax , 0B000h
 | |
| ;mov   es, ax
 | |
| ;inc   [BYTE PTR es : 0h]
 | |
| 
 | |
| 	in	al,KEYCTRL			; get the control port
 | |
| 	mov	ah,al
 | |
| 	or	al,080H				; reset bit for keyboard
 | |
| 	out	KEYCTRL,al
 | |
| 	xchg	ah,al				; get orig control data
 | |
| 	out	KEYCTRL,al			; restore control data
 | |
| 
 | |
| 	mov	ax,040h				; BIOS paragraph is always @ 040h
 | |
| 	mov	es,ax				; put in es as BIOS paragraph
 | |
| 	mov	al,[es:96h]			; get extended keys
 | |
| 	and	al,0FDh				; turn off last key e0 flag
 | |
| 	mov	[es:96h],al			; set extended keys
 | |
| 
 | |
| 	mov	al,CLEARISR			; value to clear In Service Register
 | |
| 	out	INTCHIP0,al			; 8259 interrupt chip controller 0
 | |
| 
 | |
| 	cmp [Keyboard_StackPointer],0DEADh
 | |
| 	je  ??stackok2
 | |
| 	push cx
 | |
| 	push di
 | |
| 	push ax
 | |
| 	push es
 | |
| 	mov  ax,0A000h
 | |
| 	mov  es,ax
 | |
| 	xor  di,di
 | |
| 	mov  cx,64000
 | |
| 	mov  ax,1
 | |
| 	rep  stosb
 | |
| 	pop  es
 | |
| 	pop  ax
 | |
| 	pop  di
 | |
| 	pop  cx
 | |
| ??stackok2:
 | |
| 
 | |
| 	; Restore System Stack Pointer Selector before exit Interrupt
 | |
| 	mov dx, [Keyboard_App_Stack_SS]
 | |
| 	cli				       ; disable Interrupts
 | |
| 	mov ss, dx			       ; Get Syatem Stack Selector
 | |
| 	mov sp, [Keyboard_App_Stack_ES]        ; Get Syatem Stack offset
 | |
| 	sti				       ; Enable Interrupts
 | |
| 
 | |
| ??Call_Back_Keyboard:
 | |
| 	pop	si
 | |
| 	pop	es
 | |
| 	pop	dx
 | |
| 	pop	ds
 | |
| 	pop	di
 | |
| 	pop	cx
 | |
| 	pop	bx
 | |
| 	pop	ax
 | |
| 	iret
 | |
| ENDIF
 | |
| 
 | |
| 	ENDP	Keystroke_Interrupt
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* Break interrupt routines begin here!
 | |
| ;***************************************************************************
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* BREAK_INTERRUPT -- Handles the break key interrupt                      *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:      none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* WARNINGS:    This is an interrupt routine.                              *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/13/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| label RM_Break_Interrupt
 | |
| 	GLOBAL	C Break_Interrupt:FAR
 | |
| 	PROC	Break_Interrupt C FAR
 | |
| 
 | |
| 
 | |
| 	pushf
 | |
| 	push	ax
 | |
| 	push	es
 | |
| 
 | |
| 	mov	ax,0B000h		; ES:DI = Mono RAM address.
 | |
| 	mov	es,ax
 | |
| 	inc	[BYTE PTR es:0]
 | |
| 
 | |
| 
 | |
| 	pop	es
 | |
| 	pop	ax
 | |
| 	popf
 | |
| 
 | |
| 
 | |
| 	iret
 | |
| 
 | |
| 	ENDP	Break_Interrupt
 | |
| 
 | |
| ;**************************************************************************
 | |
| ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*
 | |
| ;*                                                                         *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	none                                                                  *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:      none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   07/08/1994 SKB : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| Call_Interrupt_Chain:
 | |
| 	pushf
 | |
| 	call	Keystroke_Interrupt ;[KeyOldRMI]
 | |
| 	retf
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| ; LOW_HIDE_MOUSE:
 | |
| ;
 | |
| ; This function hides the mouse cursor on the screen if it was shown.  It
 | |
| ; will not hide the mouse if it is already hidden.
 | |
| ;
 | |
| ; PROTOTYPE:
 | |
| ;
 | |
| ;	VOID Low_Hide_Mouse(VOID);
 | |
| ;
 | |
| ; NOTE: does not check if mouse is currently being updated.
 | |
| ;
 | |
| ;----------------------------------------------------------------------------
 | |
| 
 | |
|  	GLOBAL	C Low_Hide_Mouse:FAR
 | |
| 	PROC	Low_Hide_Mouse C FAR
 | |
| 	USES	ax,bx,cx,dx,ds
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
|    	cmp	[MDisabled],0		; check if mouse is disabled
 | |
| 	jne	short ??end
 | |
| 
 | |
|    	cmp	[MState],0		; check if it was hidden before
 | |
| 	jne	short ??endnodraw		; no need to hide again
 | |
| 
 | |
| ;------	Move the saved graphic buffer to the seenpage to hide the mouse.
 | |
| ;	call	Buffer_To_Page C,[buffx],[buffy],[buffw],[buffh],[MouseBuffer],SEENPAGE
 | |
| 	mov	ax,RESTORE_VISIBLE_PAGE
 | |
| 	push	ax
 | |
| 	push	cs
 | |
| 	call	[ ShadowPtr ]
 | |
| 	add	sp,2
 | |
| 
 | |
| ;------	Record that the mouse has been hidden.
 | |
| ??endnodraw:
 | |
| 	add	[MState],1
 | |
| 	adc	[MState],0
 | |
| 
 | |
| ??end:
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	Low_Hide_Mouse
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| ; LOW_SHOW_MOUSE:
 | |
| ;
 | |
| ; This function displays the mouse cursor on the screen if it was hidden.
 | |
| ;
 | |
| ; PROTOTYPE:
 | |
| ;	VOID Low_Show_Mouse(VOID);
 | |
| ;
 | |
| ; NOTE: does not check if mouse is currently being updated.
 | |
| ;----------------------------------------------------------------------------
 | |
| 
 | |
|  	GLOBAL	C Low_Show_Mouse:FAR
 | |
| 	PROC	Low_Show_Mouse C FAR
 | |
| 	USES 	ax,bx,cx,dx,si,di,ds,es
 | |
| 	LOCAL	mousex:WORD		; Draw X position.
 | |
| 	LOCAL	mousey:WORD		; Draw Y position.
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| ;-----	Don't show the mouse if it is not hidden, disabled.
 | |
| 	cmp	[MDisabled],0		; is the mouse disabled
 | |
| 	jne	??exit			; if so then exit
 | |
| 
 | |
| 	cmp	[MState],0		; is the mouse already visible
 | |
|        	je	??exit			; if so then exit
 | |
| 
 | |
| 	dec	[MState]
 | |
| 	cmp	[MState],0		; can the mouse be shown
 | |
|        	jne	short ??exit
 | |
| 
 | |
| ;------	Determine the drawing position of the mouse.
 | |
| 	mov	cx,[MouseWidth]		; Theoretical buffer width (pixel).
 | |
| 	mov	dx,[MouseHeight]	; Theoretical buffer height (pixel).
 | |
| 
 | |
| 	mov	ax,[MouseX]
 | |
| ;	sub	ax,[MouseXHot]
 | |
| 	mov	[mousex],ax		; Draw X pixel.
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| IF 0
 | |
| ;	jns	short ??xnotneg
 | |
| ;	add	cx,ax			; Reduce width accordingly.
 | |
| ;	mov	ax,0
 | |
| ??xnotneg:
 | |
| ENDIF
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| 
 | |
| 	mov	bx,[MouseY]
 | |
| ;	sub	bx,[MouseYHot]
 | |
| 	mov	[mousey],bx		; Draw Y pixel.
 | |
| 
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| IF 0
 | |
| ;	jns	short ??ynotneg
 | |
| ;	add	dx,bx			; Reduce height of mouse accordingly.
 | |
| ;	mov	bx,0
 | |
| ??ynotneg:
 | |
| ENDIF
 | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | |
| 
 | |
| ;------	Determine the theoretical coordinates and dimensions of the
 | |
| ;	area the mouse shape will be rendered upon.
 | |
| 	mov	[MouseBuffX],ax
 | |
| 	mov	[MouseBuffY],bx
 | |
| 	mov	[MouseBuffW],cx
 | |
| 	mov	[MouseBuffH],dx
 | |
| 
 | |
| ;------	Move the area that will be drawn upon, to the graphic buffer.
 | |
| 	mov	ax,STORE_VISIBLE_PAGE
 | |
| 	push	ax
 | |
| 	push	cs
 | |
| 	call	[ ShadowPtr ]
 | |
| 	add	sp,2
 | |
| 
 | |
| ;------	Draw the mouse shape to the seenpage.
 | |
| 	push	[mousey]
 | |
| 	push	[mousex]
 | |
| 	push	cs
 | |
| 	call	[ DrawMousePtr ]
 | |
| 	add	sp,4
 | |
| ??exit:
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	Low_Show_Mouse
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| ;----------------------------------------------------------------------------
 | |
| 	GLOBAL	C Mouse_KeyNum:FAR
 | |
| 	PROC	Mouse_KeyNum C FAR
 | |
| 	USES	bx
 | |
| 	ARG	state:WORD		; Current mouse state.
 | |
| 	LOCAL	keynum:WORD		; Determined keynum.
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	mov	[keynum],KN_MOUSE_MOVE	; Presume just a mouse move.
 | |
| 	mov	bx,[state]
 | |
| 	mov	ax,bx
 | |
| 	xor	bl,[Button]		; Bits of state change.
 | |
| 	je	short ??fini
 | |
| 	mov	[Button],al		; Record new mouse state.
 | |
| 
 | |
| 	test	bl,0010b
 | |
| 	je	short ??notright
 | |
| 	mov	[keynum],KN_RMOUSE
 | |
| 	test	al,0010b
 | |
| 	jne	short ??notright
 | |
| 	or	[keynum],0800h		; Release bit on.
 | |
| ??notright:
 | |
| 
 | |
| ; DRD
 | |
| ; note:  the left mouse button has priority over the right mouse button
 | |
| ; this should be changed at a later date to process them independently
 | |
| 
 | |
| 	test	bl,0001b
 | |
| 	je	short ??notleft
 | |
| 	mov	[keynum],KN_LMOUSE
 | |
| 	test	al,0001b
 | |
| 	jne	short ??notleft
 | |
| 	or	[keynum],0800h		; Release bit on.
 | |
| ??notleft:
 | |
| 
 | |
| ??fini:
 | |
| 	mov	ax,[keynum]
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	Mouse_KeyNum
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| ; MOUSE_INT:
 | |
| ;
 | |
| ; This routine is called automatically when the Mouse_Int is installed.  It
 | |
| ; automatically updates the global variables stored in the code segment so
 | |
| ; that the mouse information is automatically known at all times.
 | |
| ;
 | |
| ; INPUTS (from int):	AX = condition mask ( bit 0 == cursor position chg,
 | |
| ;					      bit 1 == left button press,
 | |
| ;					      bit 2 == left button release,
 | |
| ;					      bit 3 == right button press,
 | |
| ;					      bit 4 == right button release,
 | |
| ;					      5-15  == not used )
 | |
| ;			BX = button state   ( bit 0 == left button down,
 | |
| ;					      bit 1 == right button down,
 | |
| ;                                             bit 2 == middle button down.
 | |
| ;					      3-15  == not used )
 | |
| ;			CX = cursor coordinate (horizontal axis)
 | |
| ;			DX = cursor coordinate (vertical axis)
 | |
| ;			DI = horizontal mouse count (mickeys)
 | |
| ;			SI = vertical mouse count (mickeys)
 | |
| ;
 | |
| ; RETURNS:		none
 | |
| ;
 | |
| ; MODIFIES:		modifies the variables _Button, _ButtonChange,
 | |
| ;			_MouseX,_MouseY,_ButtonLatch
 | |
| ;
 | |
| ; PROTOTYPE:
 | |
| ;	This routine is called from an interrupt.
 | |
| ;----------------------------------------------------------------------------
 | |
| label RM_Mouse_Interrupt
 | |
| 	PROC	Mouse_Int C FAR
 | |
| 	USES	ax,bx,cx,dx,ds,si,es,di
 | |
| 	LOCAL	cond:WORD		; Local copy of mouse event.
 | |
| 	LOCAL	state:WORD		; Local copy of button state.
 | |
| 
 | |
| 	mov	[cs:Mouse_State],bx
 | |
| 	mov	[cs:Mouse_Cond],ax
 | |
| 
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	; At this point we do not know if the SS selector is a
 | |
|  	; System Stack or the Application Stack pointer.
 | |
| 	; Soo to be in the safe side we create our own local
 | |
| 	; Stack Pointer	Selector Relative to DS
 | |
| 	; Note Do not try this trick in a reentrant interrupt
 | |
| 	mov bx, ss				; get SS
 | |
| 	mov [Mouse_App_Stack_ES], sp		; Protect ES
 | |
| 	mov [Mouse_App_Stack_SS], bx		; Protect SS
 | |
| 	lea bx, [Mouse_StackStart ]	; Compute Local Stack size
 | |
| 	and bx, -2;
 | |
| 	cli					; Disable All interrupts
 | |
| 	mov ss, ax				; Set new SS Selector
 | |
| 	mov sp, bx				; Set new Stack Offset
 | |
| 	sti					; Enable Interrupts
 | |
| 
 | |
| 
 | |
| 
 | |
| 	push ax
 | |
| 	push dx
 | |
| 
 | |
| 	mov 	dx,3c8h
 | |
| 	xor	al,al
 | |
| 	out	dx,al
 | |
| 	inc	dx
 | |
| 	out	dx,al
 | |
| 
 | |
| 	mov	dx,3c9h
 | |
| 	mov	ax,cx
 | |
| 	shr	ax,3
 | |
| 	out	dx,al
 | |
| 	jmp	??j1
 | |
| ??j1:	xor	al,al
 | |
| 	out	dx,al
 | |
| 	jmp	??j2
 | |
| ??j2:	out	dx,al
 | |
| 	jmp	??j3
 | |
| ??j3:
 | |
| 
 | |
| 	pop	dx
 | |
| 	pop	ax
 | |
| 
 | |
| 
 | |
| 
 | |
| ;------	Process the mouse interrupt only if the mouse is enabled (whether
 | |
| ;	present or not).
 | |
| 	cmp	[MDisabled],0
 | |
| 	jne	??exit
 | |
| 
 | |
| 	cmp	[MInput],0
 | |
| 	je	??exit
 | |
| 
 | |
| 
 | |
| ;------ This was added because of missing mouse presses and
 | |
| ;	releases during a mouse update.
 | |
| 	mov	ax,[Mouse_Cond]
 | |
| 	and	ax,0001EH 	; bits for left and right press and release
 | |
| 	jne	short ??dopress_release
 | |
| 
 | |
| 	cmp	[MouseUpdate],0 ; if mouse move and mouse updating exit
 | |
| 	jne	??exit
 | |
| 
 | |
| ??dopress_release:
 | |
| 
 | |
| ;------	In EEGA mode mouse X coordinates as 0..639.  Make adjustment
 | |
| ;	to keep within 0..319 range.
 | |
| 	cmp	[Adjust],1		; if the x coordinate is returned
 | |
| 	jne	short ??noadjust	; incorrectly then
 | |
| 	shr	cx,1			; adjust x coord from 640 pixel screen
 | |
| ??noadjust:
 | |
| 
 | |
| 
 | |
| ; scale mouse posX and PosY
 | |
| ;	cmp	[Adjust_XPos] , 0
 | |
| ;	jz	short ??no_scaleX
 | |
| ;	push	dx
 | |
| ;	mov	ax , [MouseRight]
 | |
| ;	imul	cx
 | |
| ;	idiv	[Adjust_XPos]
 | |
| ;	mov	cx , ax
 | |
| ;	pop	dx
 | |
| ??no_scaleX:
 | |
| ;	cmp	[Adjust_YPos] , 0
 | |
| ;	jz	short ??no_scaleY
 | |
| ;	mov	ax , [MouseBottom]
 | |
| ;	imul	dx
 | |
| ;	idiv	[Adjust_YPos]
 | |
| ;	mov	dx , ax
 | |
| ??no_scaleY:
 | |
| 
 | |
| ;------	Keep mouse within screen bounds.
 | |
| 	cmp	cx,[MouseRight]			; in EGAMODE, the mouse may go to 320
 | |
| 	jb	short ??boundX_ok		; force it to stay at least one pixel
 | |
| 	mov	cx,[MouseRight]			; on the screen
 | |
| 	dec	cx
 | |
| ??boundX_ok:
 | |
| 	cmp	dx,[MouseBottom]			; in EGAMODE, the mouse may go to 320
 | |
| 	jb	short ??boundY_ok		; force it to stay at least one pixel
 | |
| 	mov	dx,[MouseBottom]			; on the screen
 | |
| 	dec	dx
 | |
| ??boundY_ok:
 | |
| 
 | |
| 	IF 0
 | |
| ;------	Remap the middle button to equal the right button.
 | |
| 	test	bx,04h
 | |
| 	je	??noremap
 | |
| 	or	bx,0010b		; Set the right button bit.
 | |
| ??noremap:
 | |
| 	ENDIF
 | |
| 
 | |
| 	mov	[MouseX],cx		; and store in mouse x
 | |
| 	mov	[MouseY],dx		; store y coord in mouse y
 | |
| 	test	[KeyFlags],KEYMOUSE
 | |
| 	jne	short ??nostuffit
 | |
| 
 | |
| 	call	Mouse_KeyNum C,[Mouse_State]	; Convert mouse state to key number code.
 | |
| 	call	Stuff_Key_Num C,ax	; Record mouse keynumber code.
 | |
| ??nostuffit:
 | |
| 
 | |
| 
 | |
| 
 | |
| ;------ The check for Mouse in the middle of updating CAN NOT BE MOVED
 | |
| ;	any farther up because mouse presses and releases will be LOST!!
 | |
|  	cmp	[MouseUpdate],0
 | |
| 	jne	??exit
 | |
| ;??jexit:
 | |
| ;	jmp	??exit
 | |
| 
 | |
| 
 | |
| christopher:
 | |
| ??chkxy:
 | |
| 
 | |
| ;------	Signal that no mouse updating can occur at this time.
 | |
| ;	cmp	[_MouseUpdate],0
 | |
| ;	jne	??exit
 | |
| ;	mov	[_MouseUpdate],1
 | |
| 
 | |
| ;------	Perform any X movement grid adjustment.
 | |
| 	cmp	[MouseStepX],0		; are we stepping on the X?
 | |
| 	je	short ??no_x_step		; no x
 | |
| 	mov	ax,cx			; get current x_pixel
 | |
| 	mov	cx,dx			; save dx - it is trashed by idiv
 | |
| 	sub	ax,[MouseOffsetX]	; get offset difference
 | |
| 	mov	bx,[MouseStepX]	; get step in bx for idiv
 | |
| 	cwd				; extend ax -> dx:ax
 | |
| 	idiv	bx			; divide by Step X
 | |
| 	imul	bx			; ax = div * Step X
 | |
| 	add	ax,[MouseOffsetX]	; normalize to region offset
 | |
| 	mov	dx,cx			; restore dx (new MouseY)
 | |
| 	mov	cx,ax			; set cx (new MouseX)
 | |
| ??no_x_step:
 | |
| 
 | |
| ;------	Perform any Y movement grid adjustment.
 | |
| 	cmp	[MouseStepY],0		; are we stepping on the Y
 | |
| 	je	short ??no_step		; no y
 | |
| 	mov	ax,dx			; get current y_pixel
 | |
| 	sub	ax,[MouseOffsetY]	; get offset difference
 | |
| 	mov	bx,[MouseStepY]		; get step in bx for idiv
 | |
| 	cwd				; extend ax -> dx:ax
 | |
| 	idiv	bx			; divide by Step Y
 | |
| 	imul	bx			; ax = div * Step Y
 | |
| 	add	ax,[MouseOffsetY]	; normalize to region offset
 | |
| 	mov	dx,ax			; set dx (new MouseY)
 | |
| ??no_step:
 | |
| 
 | |
| ;------ Here is where we store the new MouseX and MouseY values
 | |
| ;	mov	[MouseX],cx		; and store in mouse x
 | |
| ;	mov	[MouseY],dx		; store y coord in mouse y
 | |
| 
 | |
| ;------	If the mouse is hidden or its position hasn't changed, then
 | |
| ;	perform no action.
 | |
| 	cmp	[MState],0
 | |
| 	jne	short ??updateend
 | |
| 	cmp	[MouseXOld],cx
 | |
| 	jne	short ??doit
 | |
| 	cmp	[MouseYOld],dx
 | |
| 	je	short ??updateend
 | |
| ??doit:
 | |
| 
 | |
| ;------	At this point we KNOW the mouse has moved.
 | |
| 	mov	ax,[MCState]
 | |
| 	and	ax,CONDHIDE+CONDHIDDEN
 | |
| 	cmp	ax,CONDHIDE+CONDHIDDEN
 | |
| 	je	short ??condcheck		; If already hidden.
 | |
| 
 | |
| ;------	We know that the mouse is visible, we must hide it
 | |
| ;	before we update its position.
 | |
| 	call	Low_Hide_Mouse
 | |
| 
 | |
| ;------	Conditional region check goes here.  If the mouse falls within the
 | |
| ;	conditional region, it gets marked as hidden and no other processing
 | |
| ;	occurs.
 | |
| 	test	[MCState],CONDHIDE
 | |
| 	je	short ??condok
 | |
| 
 | |
| ??condcheck:
 | |
| 	cmp	cx,[MouseCXLeft]		; check adjusted x region
 | |
| 	jb	short ??condok
 | |
| 	cmp	cx,[MouseCXRight]
 | |
| 	ja	short ??condok
 | |
| 	cmp	dx,[MouseCYUpper]	; check adjusted y region
 | |
| 	jb	short ??condok
 | |
| 	cmp	dx,[MouseCYLower]
 | |
| 	ja	short ??condok
 | |
| 
 | |
| 	or	[MCState],CONDHIDDEN	; flag as conditional hidden
 | |
| 	jmp short ??updateend
 | |
| 
 | |
| ;------	The mouse coordinates and flags pass all of the tests, proceed
 | |
| ;	with rendering the mouse.
 | |
| ??condok:
 | |
| 	call	Low_Show_Mouse
 | |
| 
 | |
| ;------	Final clean up and exit.
 | |
| ??updateend:
 | |
| 	mov	[MouseXOld],cx
 | |
| 	mov	[MouseYOld],dx
 | |
| 
 | |
| ??exit:
 | |
| 	cmp	[Mouse_StackPointer],0DEADh
 | |
| 	je	??mouse_stk_ok
 | |
| 	push cx
 | |
| 	push di
 | |
| 	push ax
 | |
| 	push es
 | |
| 	mov  ax,0A000h
 | |
| 	mov  es,ax
 | |
| 	xor  di,di
 | |
| 	mov  cx,64000
 | |
| 	mov  ax,1
 | |
| 	rep  stosb
 | |
| 	pop  es
 | |
| 	pop  ax
 | |
| 	pop  di
 | |
| 	pop  cx
 | |
| 
 | |
| ??mouse_stk_ok:
 | |
| 	; Restore System Stack Pointer Selector before exit Interrupt
 | |
| 	mov ax, [Mouse_App_Stack_SS]
 | |
| 	cli				       ; disable Interrupts
 | |
| 	mov ss, ax			       ; Get Syatem Stack Selector
 | |
| 	mov sp, [Mouse_App_Stack_ES]           ; Get Syatem Stack offset
 | |
| 	sti				       ; Enable Interrupts
 | |
| 	ret
 | |
| 	ENDP	Mouse_Int
 | |
| 
 | |
| 
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;***************************************************************************
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	int store - indicates whether we are storing the buffer or *
 | |
| ;*			    not.					   *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:	none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* PROTO:       Asm callable only!                                         *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   10/27/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| 	GLOBAL	C VGA_Mouse_Shadow_Buffer:FAR
 | |
| 	PROC	VGA_Mouse_Shadow_Buffer C FAR
 | |
| 	USES	ax,bx,cx,dx,di,si,ds,es
 | |
| 	ARG	store:WORD
 | |
| 
 | |
| 	local	x0 : word
 | |
| 	local	y0 : word
 | |
| 	local	x1 : word
 | |
| 	local	y1 : word
 | |
| 	local	buffx0 : word
 | |
| 	local	buffy0 : word
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	;* Since we are in tiny model point ds to cs
 | |
| 	;*=========================================================================*
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	; Direction flag must be forward in this routine.
 | |
| 	;*=========================================================================*
 | |
| 	cld
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Copy of X, Y, Width and Height into local registers
 | |
| 	;*===================================================================
 | |
| 	mov	ax,[MouseBuffX]
 | |
| 	mov	bx,[MouseBuffY]
 | |
| 	sub	ax , [ MouseXHot ]
 | |
| 	sub	bx , [ MouseYHot ]
 | |
| 	mov	[ x0 ] , ax
 | |
| 	mov	[ y0 ] , bx
 | |
| 
 | |
| 	add	ax , [MouseBuffW]
 | |
| 	add	bx , [MouseBuffH]
 | |
| 	mov	[ x1 ] , ax
 | |
| 	mov	[ y1 ] , bx
 | |
| 
 | |
| 	mov	[ buffx0 ] , 0
 | |
| 	mov 	ax , [ word ptr MouseBuffer ]
 | |
| 	mov	[ buffy0 ] , ax
 | |
| 
 | |
| ;*===================================================================
 | |
| ;* Bounds check source X. Y.
 | |
| ;*===================================================================
 | |
| 
 | |
| 	xor 	ax , ax
 | |
| 	xor 	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	sub	cx , [ MouseRight ]
 | |
| 	sub	bx , [ MouseRight ]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	sub	cx , [MouseBottom]
 | |
| 	sub	bx , [MouseBottom]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	xor	al , 5
 | |
| 	xor	dl , 5
 | |
| 	mov	ah , al
 | |
| 	test	dl , al
 | |
| 	jnz	??out
 | |
| 	or	al , dl
 | |
| 	jz	??acepted
 | |
| 
 | |
| 	test	ah , 1000b
 | |
| 	jz	??scr_left_ok
 | |
| 	mov	bx , [ x0 ]
 | |
| 	neg	bx
 | |
| 	mov	[ buffx0 ] , bx
 | |
| 	mov	[ x0 ] , 0
 | |
| 
 | |
| ??scr_left_ok:
 | |
| 	test	ah , 0010b
 | |
| 	jz	??scr_bottom_ok
 | |
| 	push	dx
 | |
| 	mov	ax , [ y0 ]
 | |
| 	neg	ax
 | |
| 	mul	[MouseBuffW]
 | |
| 	add	[ buffy0 ] , ax
 | |
| 	mov	[ y0 ] , 0
 | |
| 	pop	dx
 | |
| 
 | |
| ??scr_bottom_ok:
 | |
| 	test	dl , 0100b
 | |
| 	jz	??scr_right_ok
 | |
| 	mov	ax , [MouseRight]  ; get width into register
 | |
| 	mov	[ x1 ] , ax
 | |
| ??scr_right_ok:
 | |
| 	test	dl , 0001b
 | |
| 	jz	??acepted
 | |
| 	mov	ax , [MouseBottom]  ; get width into register
 | |
| 	mov	[ y1 ] , ax
 | |
| 
 | |
| ??acepted:
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Get the offset into the screen.
 | |
| 	;*===================================================================
 | |
| 
 | |
| 	mov	ax,0A000h
 | |
| 	mov	es,ax
 | |
| 
 | |
| 	mov	ax , [ y0 ]
 | |
| 	mul	[ MouseRight ]
 | |
| 	mov	dx , [MouseRight]
 | |
| 	mov	di , ax
 | |
| 	add	di , [ x0 ]
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Adjust the source for the top clip.
 | |
| 	;*===================================================================
 | |
| 	mov	bx , [ MouseWidth ]	; turn this into an offset
 | |
| 	lds	si , [ MouseBuffer ]
 | |
| 	mov	si , [ buffy0 ]		; edx points to source
 | |
| 	add	si , [ buffx0 ]		; plus clipped lines
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Calculate the bytes per row add value
 | |
| 	;*===================================================================
 | |
| 
 | |
| 	mov	ax , [ x1 ]
 | |
| 	mov	cx , [ y1 ]
 | |
| 	sub	ax , [ x0 ]
 | |
| 	jle	??out
 | |
| 	sub	cx , [ y0 ]
 | |
| 	jle	??out
 | |
| 
 | |
| 	sub	dx , ax
 | |
| 	sub	bx , ax
 | |
| 
 | |
| 	push	bp
 | |
| 	cmp	[store],RESTORE_VISIBLE_PAGE		; are we restoring page?
 | |
| 	jne	??store_entry				; if not the go to store
 | |
| 	;*===================================================================
 | |
| 	;* Handle restoring the buffer to the visible page
 | |
| 	;*===================================================================
 | |
| 	mov	bp , cx
 | |
| ??restore_loop:
 | |
| 	mov	cx,ax					; get number to really write
 | |
| 	rep	movsb					; store them into the buffer
 | |
| 	add	si,bx				; move past right clipped pixels
 | |
| 	add	di,dx					; adjust dest to next line
 | |
| 	dec	bp					; decrement number of rows to do
 | |
| 	jnz	??restore_loop				; if more to do, do it
 | |
| 	pop	bp
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 12 * 80 + 10
 | |
| mov es, ax
 | |
| mov al , 'V'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 
 | |
| 	ret
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Handle soting the visible page into the Mouse Shadow Buffer
 | |
| 	;*===================================================================
 | |
| ??store_entry:
 | |
| 	xchg	si,di					; xchg the source and the dest
 | |
| 	mov	bp , cx
 | |
| 	push	es					; need to swap es and ds but
 | |
| 	push	ds					;   cant xchg so pop them on the
 | |
| 	pop	es					;   stack and pop them off the
 | |
| 	pop	ds					;   wrong way intentionally.
 | |
| ??store_loop:
 | |
| 	mov	cx,ax					; get number to really write
 | |
| 	rep	movsb					; store them into the buffer
 | |
| 	add	si,dx					; move past right clipped pixels
 | |
| 	add	di,bx					; adjust dest to next line
 | |
| 	dec	bp					; decrement number of rows to do
 | |
| 	jnz	??store_loop				; if more to do, do it
 | |
| 	pop	bp
 | |
| ??out:
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 12 * 80 + 12
 | |
| mov es, ax
 | |
| mov al , 'G'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	VGA_Mouse_Shadow_Buffer
 | |
| 
 | |
| ;***************************************************************************
 | |
| 
 | |
| 	GLOBAL	C VGA_Draw_Mouse:FAR
 | |
| 	PROC	VGA_Draw_Mouse C FAR
 | |
| 	USES	ax,bx,cx,dx,di,si,ds,es
 | |
| 	ARG	mousex:WORD
 | |
| 	ARG	mousey:WORD
 | |
| 
 | |
| 	local	x0 : word
 | |
| 	local	y0 : word
 | |
| 	local	x1 : word
 | |
| 	local	y1 : word
 | |
| 	local	buffx0 : word
 | |
| 	local	buffy0 : word
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	;* Since we are in tiny model point ds to cs
 | |
| 	;*=========================================================================*
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Pre-initialize the left, right and topclip values to zero.
 | |
| 	;*===================================================================
 | |
| 	mov	ax, [ mousex ]
 | |
| 	mov	bx , [ mousey ]
 | |
| 	sub	ax , [ MouseXHot ]
 | |
| 	sub	bx , [ MouseYHot ]
 | |
| 	mov	[ x0 ] , ax
 | |
| 	mov	[ y0 ] , bx
 | |
| 	add	ax, [ MouseWidth ]
 | |
| 	add	bx, [ MouseHeight ]
 | |
| 	mov	[ x1 ] , ax
 | |
| 	mov	[ y1 ] , bx
 | |
| 
 | |
| 	mov	[ buffx0 ] , 0
 | |
| 	les	ax , [ MouseCursor ]
 | |
| 	mov	[ buffy0 ] , ax
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Bounds check source X. Y.
 | |
| 	;*===================================================================
 | |
| 
 | |
| 	xor 	ax , ax
 | |
| 	xor 	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	sub	cx , [ MouseRight ]
 | |
| 	sub	bx , [ MouseRight ]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	sub	cx , [MouseBottom]
 | |
| 	sub	bx , [MouseBottom]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	xor	al , 5
 | |
| 	xor	dl , 5
 | |
| 
 | |
| 	mov	ah , al
 | |
| 	test	dl , al
 | |
| 	jnz	??out
 | |
| 	or	al , dl
 | |
| 	jz	??acepted
 | |
| 
 | |
| 	test	ah , 1000b
 | |
| 	jz	??scr_left_ok
 | |
| 	mov	bx , [ x0 ]
 | |
| 	neg	bx
 | |
| 	mov	[ buffx0 ] , bx
 | |
| 	mov	[ x0 ] , 0
 | |
| 
 | |
| ??scr_left_ok:
 | |
| 	test	ah , 0010b
 | |
| 	jz	??scr_bottom_ok
 | |
| 	push	dx
 | |
| 	mov	ax , [ y0 ]
 | |
| 	neg	ax
 | |
| 	mul	[MouseWidth]
 | |
| 	add	[ buffy0 ] , ax
 | |
| 	mov	[ y0 ] , 0
 | |
| 	pop	dx
 | |
| 
 | |
| ??scr_bottom_ok:
 | |
| 	test	dl , 0100b
 | |
| 	jz	??scr_right_ok
 | |
| 	mov	bx , [MouseRight]  ; get width into register
 | |
| 	mov	[ x1 ] , bx
 | |
| ??scr_right_ok:
 | |
| 	test	dl , 0001b
 | |
| 	jz	??acepted
 | |
| 	mov	bx , [MouseBottom]  ; get width into register
 | |
| 	mov	[ y1 ] , bx
 | |
| 
 | |
| ??acepted:
 | |
| 
 | |
| 	mov	ax , [ y0 ]
 | |
| 	mul	[ MouseRight ]
 | |
| 	mov	dx , [MouseRight]
 | |
| 	mov	di , ax
 | |
| 	add	di , [ x0 ]
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Adjust the source for the top clip.
 | |
| 	;*===================================================================
 | |
| 	mov	bx , [MouseWidth]	; turn this into an offset
 | |
| 	mov	si , [ buffy0 ]		; edx points to source
 | |
| 	add	si , [ buffx0 ]		; plus clipped lines
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Calculate the bytes per row add value
 | |
| 	;*===================================================================
 | |
| 	mov	ax , 0a000h
 | |
| 	mov	ds , ax
 | |
| 	mov	ax , [ x1 ]
 | |
| 	mov	cx , [ y1 ]
 | |
| 	sub	ax , [ x0 ]
 | |
| 	jle	??out
 | |
| 	sub	cx , [ y0 ]
 | |
| 	jle	??out
 | |
| 
 | |
| 	sub	dx , ax
 | |
| 	sub	bx , ax
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Handle restoring the buffer to the visible page
 | |
| 	;*===================================================================
 | |
| ??top_loop:
 | |
| 	mov	ah,al
 | |
| ??inner_loop:
 | |
| 	mov	ch , [es:si]
 | |
| 	inc	esi
 | |
| 	or	ch,ch
 | |
| 	jz	??inc_edi
 | |
| 	mov	[di],ch
 | |
| ??inc_edi:
 | |
| 	inc	di
 | |
| 	dec	ah
 | |
| 	jnz	??inner_loop
 | |
| 	add	si,bx				; move past right clipped pixels
 | |
| 	add	di,dx				; adjust dest to next line
 | |
| 	dec	cl					; decrement number of rows to do
 | |
| 	jnz	??top_loop				; if more to do, do it
 | |
| ??out:
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 12 * 80 + 14
 | |
| mov es, ax
 | |
| mov al , 'A'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 	ret
 | |
| ENDP	VGA_Draw_Mouse
 | |
| 
 | |
| 
 | |
| ;***************************************************************************
 | |
| ;***************************************************************************
 | |
| ;***************************************************************************
 | |
| ;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer   *
 | |
| ;*                                                                         *
 | |
| ;* INPUT:	int store - indicates whether we are storing the buffer or *
 | |
| ;*			    not.					   *
 | |
| ;*                                                                         *
 | |
| ;* OUTPUT:	none                                                       *
 | |
| ;*                                                                         *
 | |
| ;* PROTO:       Asm callable only!                                         *
 | |
| ;*                                                                         *
 | |
| ;* HISTORY:                                                                *
 | |
| ;*   10/27/1994 PWG : Created.                                             *
 | |
| ;*=========================================================================*
 | |
| 	GLOBAL	C VESA_Mouse_Shadow_Buffer:FAR
 | |
| 	PROC	VESA_Mouse_Shadow_Buffer C FAR
 | |
| 	USES	ax,bx,cx,dx,di,si,ds,es
 | |
| 	ARG	store:WORD
 | |
| 
 | |
| 	local	x0 : word
 | |
| 	local	y0 : word
 | |
| 	local	x1 : word
 | |
| 	local	y1 : word
 | |
| 	local	buffx0 : word
 | |
| 	local	buffy0 : word
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	;* Since we are in tiny model point ds to cs
 | |
| 	;*=========================================================================*
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	call	get_vesa_window
 | |
| 	mov	[ app_vesa_window ] , dx
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	; Direction flag must be forward in this routine.
 | |
| 	;*=========================================================================*
 | |
| 	cld
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Copy of X, Y, Width and Height into local registers
 | |
| 	;*===================================================================
 | |
| 	mov	ax,[MouseBuffX]
 | |
| 	mov	bx,[MouseBuffY]
 | |
| 	sub	ax , [ MouseXHot ]
 | |
| 	sub	bx , [ MouseYHot ]
 | |
| 
 | |
| 	mov	[ x0 ] , ax
 | |
| 	mov	[ y0 ] , bx
 | |
| 	add	ax , [MouseBuffW]
 | |
| 	add	bx , [MouseBuffH]
 | |
| 	mov	[ x1 ] , ax
 | |
| 	mov	[ y1 ] , bx
 | |
| 
 | |
| 	mov	[ buffx0 ] , 0
 | |
| 	mov 	ax , [ word ptr MouseBuffer ]
 | |
| 	mov	[ buffy0 ] , ax
 | |
| 
 | |
| ;*===================================================================
 | |
| ;* Bounds check source X. Y.
 | |
| ;*===================================================================
 | |
| 
 | |
| 	xor 	ax , ax
 | |
| 	xor 	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	sub	cx , [ MouseRight ]
 | |
| 	sub	bx , [ MouseRight ]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	sub	cx , [MouseBottom]
 | |
| 	sub	bx , [MouseBottom]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	xor	al , 5
 | |
| 	xor	dl , 5
 | |
| 	mov	ah , al
 | |
| 	test	dl , al
 | |
| 	jnz	??out
 | |
| 	or	al , dl
 | |
| 	jz	??acepted
 | |
| 
 | |
| 	test	ah , 1000b
 | |
| 	jz	??scr_left_ok
 | |
| 	mov	bx , [ x0 ]
 | |
| 	neg	bx
 | |
| 	mov	[ buffx0 ] , bx
 | |
| 	mov	[ x0 ] , 0
 | |
| 
 | |
| ??scr_left_ok:
 | |
| 	test	ah , 0010b
 | |
| 	jz	??scr_bottom_ok
 | |
| 	push	dx
 | |
| 	mov	ax , [ y0 ]
 | |
| 	neg	ax
 | |
| 	mul	[MouseBuffW]
 | |
| 	add	[ buffy0 ] , ax
 | |
| 	mov	[ y0 ] , 0
 | |
| 	pop	dx
 | |
| 
 | |
| ??scr_bottom_ok:
 | |
| 	test	dl , 0100b
 | |
| 	jz	??scr_right_ok
 | |
| 	mov	ax , [MouseRight]  ; get width into register
 | |
| 	mov	[ x1 ] , ax
 | |
| ??scr_right_ok:
 | |
| 	test	dl , 0001b
 | |
| 	jz	??acepted
 | |
| 	mov	ax , [MouseBottom]  ; get width into register
 | |
| 	mov	[ y1 ] , ax
 | |
| 
 | |
| ??acepted:
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Get the offset into the screen.
 | |
| 	;*===================================================================
 | |
| 	mov	ax,0A000h
 | |
| 	mov	es,ax
 | |
| 
 | |
| 	mov	ax , [ y0 ]
 | |
| 	mul	[ MouseRight ]
 | |
| 
 | |
| 	add	ax , [ x0 ]
 | |
| 	adc	dx , 0
 | |
| 	mov	di , ax
 | |
| 	call	set_vesa_page
 | |
| 	mov	dx , [MouseRight]
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Adjust the source for the top clip.
 | |
| 	;*===================================================================
 | |
| 
 | |
| 
 | |
| 	mov	bx , [ MouseWidth ]	; turn this into an offset
 | |
| 	lds	si , [ MouseBuffer ]
 | |
| 	mov	si , [ buffy0 ]		; edx points to source
 | |
| 	add	si , [ buffx0 ]		; plus clipped lines
 | |
| 
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Calculate the bytes per row add value
 | |
| 	;*===================================================================
 | |
| 
 | |
| 	mov	ax , [ x1 ]
 | |
| 	mov	cx , [ y1 ]
 | |
| 	sub	ax , [ x0 ]
 | |
| 	jle	??out
 | |
| 	sub	cx , [ y0 ]
 | |
| 	jle	??out
 | |
| 
 | |
| 	sub	dx , ax
 | |
| 	sub	bx , ax
 | |
| 
 | |
| 	cmp	[store],RESTORE_VISIBLE_PAGE		; are we restoring page?
 | |
| 	jne	??store_entry				; if not the go to store
 | |
| 	;*===================================================================
 | |
| 	;* Handle restoring the buffer to the visible page
 | |
| 	;*===================================================================
 | |
| ??restore_loop:
 | |
| 	mov	ah,al
 | |
| ??res_inner_loop:
 | |
| 	mov	ch , [si]
 | |
| 	mov	[es:di],ch
 | |
| 	inc	si
 | |
| 	inc	di
 | |
| 	jnz	??res_same_page
 | |
| 	call	next_vesa_page
 | |
|  ??res_same_page:
 | |
|  	dec	ah
 | |
| 	jnz	??res_inner_loop
 | |
| 	add	si,bx				; move past right clipped pixels
 | |
| 	add	di,dx				; adjust dest to next line
 | |
| 	jnc	??res_same_page1
 | |
| 	call	next_vesa_page
 | |
|  ??res_same_page1:
 | |
| 	dec	cl					; decrement number of rows to do
 | |
| 	jnz	??restore_loop
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 10 * 80 + 10
 | |
| mov es,ax
 | |
| mov al ,'v'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 	jmp	??out
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Handle soting the visible page into the Mouse Shadow Buffer
 | |
| 	;*===================================================================
 | |
| ??store_entry:
 | |
| 	mov	ah,al
 | |
| ??store_inner_loop:
 | |
| 	mov	ch , [es:di]
 | |
| 	mov	[si],ch
 | |
| 	inc	si
 | |
| 	inc	di
 | |
| 	jnz	??store_same_page
 | |
| 	call	next_vesa_page
 | |
|  ??store_same_page:
 | |
|  	dec	ah
 | |
| 	jnz	??store_inner_loop
 | |
| 	add	si,bx				; move past right clipped pixels
 | |
| 	add	di,dx				; adjust dest to next line
 | |
| 	jnc	??store_same_page1
 | |
| 	call	next_vesa_page
 | |
|  ??store_same_page1:
 | |
| 	dec	cl					; decrement number of rows to do
 | |
| 	jnz	??store_entry
 | |
| ??out:
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 10 * 80 + 14
 | |
| mov es,ax
 | |
| mov al ,'e'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 
 | |
| 	mov	dx , [ app_vesa_window ]
 | |
| 	call	set_vesa_window
 | |
| 	ret
 | |
| 
 | |
| 	ENDP	VESA_Mouse_Shadow_Buffer
 | |
| 
 | |
| 
 | |
| 
 | |
| ;***************************************************************************
 | |
| 
 | |
| 	GLOBAL	C VESA_Draw_Mouse:FAR
 | |
| 	PROC	VESA_Draw_Mouse C FAR
 | |
| 	USES	ax,bx,cx,dx,di,si,ds,es
 | |
| 	ARG	mousex:WORD
 | |
| 	ARG	mousey:WORD
 | |
| 
 | |
| 	local	x0 : word
 | |
| 	local	y0 : word
 | |
| 	local	x1 : word
 | |
| 	local	y1 : word
 | |
| 	local	buffx0 : word
 | |
| 	local	buffy0 : word
 | |
| 	local	app_vesa_window : word
 | |
| 
 | |
| 
 | |
| 	;*=========================================================================*
 | |
| 	;* Since we are in tiny model point ds to cs
 | |
| 	;*=========================================================================*
 | |
| 	mov	ax,cs				; since we are in tiny model
 | |
| 	mov	ds,ax				; set cs = ds
 | |
| 
 | |
| 	call	get_vesa_window
 | |
| 	mov	[ app_vesa_window ] , dx
 | |
| 
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Pre-initialize the left, right and topclip values to zero.
 | |
| 	;*===================================================================
 | |
| 	mov	ax, [ mousex ]
 | |
| 	mov	bx , [ mousey ]
 | |
| 	sub	ax , [ MouseXHot ]
 | |
| 	sub	bx , [ MouseYHot ]
 | |
| 
 | |
| 	mov	[ x0 ] , ax
 | |
| 	mov	[ y0 ] , bx
 | |
| 	add	ax, [ MouseWidth ]
 | |
| 	add	bx, [ MouseHeight ]
 | |
| 	mov	[ x1 ] , ax
 | |
| 	mov	[ y1 ] , bx
 | |
| 
 | |
| 	mov	[ buffx0 ] , 0
 | |
| 	les	ax , [ MouseCursor ]
 | |
| 	mov	[ buffy0 ] , ax
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Bounds check source X. Y.
 | |
| 	;*===================================================================
 | |
| 
 | |
| 	xor 	ax , ax
 | |
| 	xor 	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ x0 ]
 | |
| 	mov	bx , [ x1 ]
 | |
| 	sub	cx , [ MouseRight ]
 | |
| 	sub	bx , [ MouseRight ]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	mov	cx , [ y0 ]
 | |
| 	mov	bx , [ y1 ]
 | |
| 	sub	cx , [MouseBottom]
 | |
| 	sub	bx , [MouseBottom]
 | |
| 	dec	cx
 | |
| 	dec	bx
 | |
| 	add	cx , cx
 | |
| 	adc	ax , ax
 | |
| 	add	bx , bx
 | |
| 	adc	dx , dx
 | |
| 
 | |
| 	xor	al , 5
 | |
| 	xor	dl , 5
 | |
| 	mov	ah , al
 | |
| 	test	dl , al
 | |
| 	jnz	??out
 | |
| 	or	al , dl
 | |
| 	jz	??acepted
 | |
| 
 | |
| 
 | |
| 	test	ah , 1000b
 | |
| 	jz	??scr_left_ok
 | |
| 	mov	bx , [ x0 ]
 | |
| 	neg	bx
 | |
| 	mov	[ buffx0 ] , bx
 | |
| 	mov	[ x0 ] , 0
 | |
| 
 | |
| ??scr_left_ok:
 | |
| 	test	ah , 0010b
 | |
| 	jz	??scr_bottom_ok
 | |
| 	push	dx
 | |
| 	mov	ax , [ y0 ]
 | |
| 	neg	ax
 | |
| 	mul	[MouseWidth]
 | |
| 	add	[ buffy0 ] , ax
 | |
| 	mov	[ y0 ] , 0
 | |
| 	pop	dx
 | |
| 
 | |
| ??scr_bottom_ok:
 | |
| 	test	dl , 0100b
 | |
| 	jz	??scr_right_ok
 | |
| 	mov	ax , [MouseRight]  ; get width into register
 | |
| 	mov	[ x1 ] , ax
 | |
| ??scr_right_ok:
 | |
| 	test	dl , 0001b
 | |
| 	jz	??acepted
 | |
| 	mov	ax , [MouseBottom]  ; get width into register
 | |
| 	mov	[ y1 ] , ax
 | |
| 
 | |
| ??acepted:
 | |
| 
 | |
| 	mov	ax , [ y0 ]
 | |
| 	mul	[ MouseRight ]
 | |
| 
 | |
| 	add	ax , [ x0 ]
 | |
| 	adc	dx , 0
 | |
| 	mov	di , ax
 | |
| 	call	set_vesa_page
 | |
| 
 | |
| 	mov	dx , [MouseRight]
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Adjust the source for the top clip.
 | |
| 	;*===================================================================
 | |
| 	mov	bx , [MouseWidth]	; turn this into an offset
 | |
| 	mov	si , [ buffy0 ]		; edx points to source
 | |
| 	add	si , [ buffx0 ]		; plus clipped lines
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Calculate the bytes per row add value
 | |
| 	;*===================================================================
 | |
| 	mov	ax , 0a000h
 | |
| 	mov	ds , ax
 | |
| 	mov	ax , [ x1 ]
 | |
| 	mov	cx , [ y1 ]
 | |
| 	sub	ax , [ x0 ]
 | |
| 	jle	??out
 | |
| 	sub	cx , [ y0 ]
 | |
| 	jle	??out
 | |
| 
 | |
| 	sub	dx , ax
 | |
| 	sub	bx , ax
 | |
| 
 | |
| 	;*===================================================================
 | |
| 	;* Handle restoring the buffer to the visible page
 | |
| 	;*===================================================================
 | |
| ??top_loop:
 | |
| 	mov	ah,al
 | |
| ??inner_loop:
 | |
| 	mov	ch , [es:si]
 | |
| 	inc	si
 | |
| 	or	ch,ch
 | |
| 	jz	??inc_edi
 | |
| 	mov	[di],ch
 | |
| ??inc_edi:
 | |
| 	inc	di
 | |
| 	jnz	??same_page
 | |
| 	call	next_vesa_page
 | |
|  ??same_page:
 | |
|  	dec	ah
 | |
| 	jnz	??inner_loop
 | |
| 	add	si,bx				; move past right clipped pixels
 | |
| 	add	di,dx				; adjust dest to next line
 | |
| 	jnc	??same_page1
 | |
| 	call	next_vesa_page
 | |
|  ??same_page1:
 | |
| 	dec	cl					; decrement number of rows to do
 | |
| 	jnz	??top_loop				; if more to do, do it
 | |
| ??out:
 | |
| 
 | |
| IF  ECHOON
 | |
| mov ax , 0b000h
 | |
| mov di , 10 * 80 + 14
 | |
| mov es, ax
 | |
| mov al , 's'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| mov di , 10 * 80 + 16
 | |
| mov al , 'a'
 | |
| mov [es:di],al
 | |
| mov al,2
 | |
| mov [es:di+1],al
 | |
| ENDIF
 | |
| 	mov	dx , [ app_vesa_window ]
 | |
| 	call	set_vesa_window
 | |
| 	ret
 | |
| 
 | |
| 
 | |
| ENDP	VESA_Draw_Mouse
 | |
| 
 | |
| 
 | |
| 
 | |
| ;************************************************************************
 | |
| 
 | |
| PROC	get_vesa_window C near
 | |
| uses	ax,bx
 | |
| 	mov	ax , 04f05h
 | |
| 	mov	bh , 1
 | |
| 	mov	bl , 0
 | |
| 	call	[ dword ptr cs: VesaPtr ]
 | |
| 	ret
 | |
| ENDP
 | |
| 
 | |
| ;************************************************************************
 | |
| 
 | |
| PROC	set_vesa_window C near
 | |
| uses	ax,bx,dx
 | |
| 	mov	ax , 04f05h
 | |
| 	mov	bh , 0
 | |
| 	mov	bl , 0
 | |
| 	call	[ dword ptr cs: VesaPtr ]
 | |
| 	ret
 | |
| ENDP
 | |
| 
 | |
| 
 | |
| ;***************************************************************************
 | |
| 
 | |
| PROC	set_vesa_page C near
 | |
| USES	ax,bx,dx
 | |
| 
 | |
| 	mov	bx , dx
 | |
| 	shl	bx , 2
 | |
| 	mov	[ cs: current_page ] , bx
 | |
| 	mov	dx , [ word ptr cs:banktable + bx ]
 | |
| 	mov	ax , 04f05h
 | |
| 	mov	bh , 0
 | |
| 	mov	bl , 0
 | |
| 	call	[ dword ptr cs: VesaPtr ]
 | |
| 	ret
 | |
| ENDP	set_vesa_page
 | |
| 
 | |
| PROC	next_vesa_page C near
 | |
| USES	ax,bx,dx
 | |
| 	mov	bx , [ cs: current_page ]
 | |
| 	add	bx , 4
 | |
| 	mov	[ cs:current_page ] , bx
 | |
| 	mov	dx , [ word ptr cs:banktable + bx ]
 | |
|        	mov	ax , 04f05h
 | |
| 	mov	bh , 0
 | |
| 	mov	bl , 0
 | |
| 	call	[ dword ptr cs: VesaPtr ]
 | |
| 	ret
 | |
| ENDP	next_vesa_page
 | |
| 
 | |
| 
 | |
| 
 | |
| ;***********************************************************
 | |
| END
 | 
