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
|