home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 21
/
CD_ASCQ_21_040595.iso
/
dos
/
prg
/
c
/
xlib612
/
source
/
xmouse.asm
< prev
next >
Wrap
Assembly Source File
|
1994-07-15
|
24KB
|
885 lines
;-----------------------------------------------------------------------
; MODULE XMOUSE
;
; Mouse functions functions for all MODE X 256 Color resolutions
;
; Compile with Tasm.
; C callable.
;
; ****** XLIB - Mode X graphics library ****************
; ****** ****************
; ****** Written By Themie Gouthas ****************
;
; This module is based on Shane Hyde's module of the same name,
; posted to Rec.Games.Programmer, October 92.
;
;
; egg@dstos3.dsto.gov.au
; teg@bart.dsto.gov.au
;
; mouse cursor shape by Tiaan A Geldenhuys
;
;-----------------------------------------------------------------------
COMMENT $
This is a module implementing very basic mouse functions.
It does not support the full functionality of:
SPLIT SCREENS
SCROLLED WINDOWS
VIRTUAL WINDOWS
--------------------------------------
MS Mouse Driver Functions
Mouse Initialization 0
Show Cursor 1
Hide Cursor 2
Get Mouse Position & Button Status 3
Set Mouse Cursor Position 4
Get Button Press Information 5
Get Button Release Information 6
Set Min/Max Horizontal Position 7
Set Min/Max Vertical Position 8
Define Graphics Cursor Block 9
Define Text Cursor 10
Read Mouse Motion Counters 11
Define Event Handler 12
Light Pen Emulation Mode ON 13
Light Pen Emulation Mode OFF 14
Set Mouse Mickey/Pixel Ratio 15
Conditional Hide Cursor 16
Set Double-Speed Threshold 19
--------------------------------------
$
include xlib.inc
include xdetect.inc
.data
global _MouseInstalled :word
global _MouseHidden :word
global _MouseButtonStatus :word
global _MouseX :word
global _MouseY :word
global _MouseFrozen :byte
global _MouseColor :byte
global _x_define_mouse_cursor :proc
global _x_show_mouse :proc
global _x_hide_mouse :proc
global _x_mouse_remove :proc
global _x_position_mouse :proc
global _x_put_cursor :proc
global _x_update_mouse :proc
global _x_mouse_init :proc
global _x_mouse_window :proc
ALIGN 2
InitMouseDef db 00000001b ; Default mouse mask, note the reverse order
db 00000011b
db 00000111b
db 00001111b
db 00011111b
db 00111111b
db 01111111b
db 11111111b
db 00011111b
db 00011011b
db 00110001b
db 00110000b
db 01100000b
db 01100000b
COMMENT $
Old mouse definition
InitMouseDef db 00000001b ; Default mouse mask, note the reverse order
db 00000011b
db 00000111b
db 00001111b
db 00011111b
db 00111111b
db 01111111b
db 11111111b
db 00011100b
db 00111100b
db 01111100b
db 00000000b
db 00000000b
db 00000000b
$
MouseMask db 168 dup(?)
OldHandlerSeg dw ?
OldHandlerOffs dw ?
OldHandlerMask dw ?
OldX dw ?
OldY dw ?
OldScrnOffs dw ?
BGSaveOffs dw 0
_MouseInstalled dw 0 ; Flag indicating whether mouse is installed
_MouseHidden dw 0 ; Flag indicating whether mouse is hidden
_MouseButtonStatus dw 0 ; Holds current button press information
_MouseX dw 0 ; Coords of cursor hot spot
_MouseY dw 0
_MouseFrozen db 0 ; Mouse motion enable/disable control
_MouseColor db 0 ; Mouse cursor colour
inhandler db 0
.code
;----------------------------------------------------------------------
; Local function that updates the cursor position
;
; Destroys SI,DI,AX,BX
;
;----------------------------------------------------------------------
update_cursor proc near
WaitVsyncStart
mov di,[OldScrnOffs] ; Delete cursor (restore old background)
mov ax,[OldY]
mov bx,[OldX]
call restorebg
mov si,[_VisiblePageOffs] ; Save cursor background
mov ax,[_MouseY]
mov bx,[_MouseX]
mov [OldScrnOffs],si
mov [OldY],ax
mov [OldX],bx
call getbg
push [_VisiblePageOffs] ; Draw the cursor
mov ax,[_ScrnPhysicalHeight]
push ax
mov ax,0
push ax
push [OldY]
push [OldX]
call _x_put_cursor
add sp,10
ret
update_cursor endp
;----------------------------------------------------------------------
; x_mouse_init - Initialise Mode X mouse handler
;
; C Prototype
;
; int x_mouse_init()
;
; This is the first function you must call before using any of the mouse
; functions
;
; WARNING: This function uses and updates "NonVisual_Offset" to allocate
; video ram for the saved mouse background.
;
; This mouse code uses the fastest possible techniques to save and restore
; mouse backgrounds and to draw the mouse cursor.
;
; LIMITATIONS: No clipping is supported horizontally for the mouse cursor
; No validity checking is performed for NonVisual_Offs
;
;
; **WARNING** Hide or freeze mouse while drawing using any of the other
; Modules. VGA register settings are not preserved which will
; result in unpredictable drawing behavior.
; If you know the drawing will occur away from the mouse cursor
; set MouseFrozen to TRUE (1), do your drawing then set it to
; FALSE (0). Alternatively call "x_hide_mouse", perform your
; drawing and then call "x_show_mouse"
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_mouse_init proc
push bp
mov bp,sp
cmp [_MouseButtonCount],0 ; Dont initialize if mouse detection
jne @@DontInitialize ; or initialization function previously
; called
xor ax,ax ; FUNC 0: Mouse Initialization
int 33h ;
or ax,ax ; Is there a mouse installed ?
jz @@Done
mov [_MouseButtonCount],bx ; Set the button count
@@DontInitialize:
mov [_MouseInstalled],ax
or ax,ax ; Do we have an installed mouse driver ?
jz @@Done ; Nop!
mov ax,[_NonVisual_Offs]; ; Allocate VRAM for saved background
mov BGSaveOffs,ax
add ax,14*3
mov [_NonVisual_Offs],ax ; Update NonVisualOffset
mov ax,02 ; FUNC 2: Hide Cursor
int 33h ; (hide the mouse driver's default cursor)
mov _MouseInstalled,TRUE ; Indicate user mouse driver present
mov ax,07h ; FUNC 7:Set min/max horizontal position
mov cx,0
mov dx,[_ScrnPhysicalPixelWidth]
shl dx,1 ; Mult X by 2 as cursor steps by 2 pixels
int 33h ; 0 < X < _ScrnPhysicalPixelWidth
mov ax,08h ; FUNC 8:Set min/max vertical position
mov cx,0
mov dx,_ScrnPhysicalHeight
int 33h ; 0 < Y < _ScrnPhysicalHeight
mov ax,0fh ; FUNC 15: Mouse Hor/Vert resolution
mov cx,4 ; Horiz speed >> Value => << Speed
mov dx,8 ; Vert Speed
int 33h
mov ax,3 ; FUNC 3: Get mouse pos & button status
int 33h
mov [_MouseY],dx
shr cx,1
mov [_MouseX],cx
mov ax,12 ; FUNC 12: Define Event Handler
mov bx,seg mouse_handler ; ES:DX -> Event handler
mov es,bx
mov dx,offset mouse_handler
mov cx,1fh ; Set handler for all events
int 33h
mov [_MouseHidden],TRUE ; Mouse initially hidden
push ds ; Set the default cursor shape
mov ax,offset InitMouseDef
push ax
call _x_define_mouse_cursor
add sp,04h
mov ax,[_MouseInstalled] ; Return MouseInstalled flag
@@Done:
pop bp
ret
_x_mouse_init endp
;----------------------------------------------------------------------
; x_mouse_window - Define a mouse window
;
; C Prototype
;
; void x_mouse_window(int x0, int y0, int x1, int y1);
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_mouse_window proc
ARG x0:word,y0:word,x1:word,y1:word
push bp
mov bp,sp
mov ax,7 ; FUNC 7: Set X range
mov cx,x0
shl cx,1
mov dx,x1
shl dx,1
int 33h
mov ax,8 ; FUNC 8: Set Y range
mov cx,y0
mov dx,y1
int 33h
pop bp
ret
_x_mouse_window endp
;----------------------------------------------------------------------
; x_define_mouse_cursor - Define a mouse cursor from an input bitmask
;
; C Prototype
;
; void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)
;
; WARNING: This function assumes MouseDef points to 14 bytes.
;
; Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..
; bit 0 represents pixel 7 in each "MouseDef" byte.
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_define_mouse_cursor proc
ARG MouseDef:dword,MouseColor:byte
push bp
mov bp,sp
cmp [_MouseInstalled],FALSE ; Check whether we have installed
je @@Done ; our mouse handler and leave if not
mov al,[MouseColor] ; Set the mouse pointers color
mov [_MouseColor],al
push si
push di
push ds
mov ax,ds ; ES:DI -> Stored plane mask for all
mov es,ax ; pixel alignments of mouse cursor
mov di,offset MouseMask
lds si,MouseDef
xor cl,cl ; CL = current alignment (initially zero)
@@AlignmentLoop:
push si ; save MouseDef ptr for next alignment
mov dh,14 ; Init Row counter to Cursor Height
@@RowLoop:
lodsb ; Load first cursor def byte each bit
; representing pixel in the row
xor ah,ah ; AH is the shift overflow byte
shl ax,cl ; Shift mask for current alignment
mov bl,al ; store first three nibbles of ax into
and bl,0fh ; consecutive bytes in the destination
mov es:[di],bl ; buffer
inc di
shr al,4
stosw
dec dh ; Next row for this alignment if there
jnz @@RowLoop ; are more to do
pop si ; point to the start of the cursor def.
inc cl ; Select next pixel alignment
cmp cl,4 ; If there are more alignments to do
jne @@AlignmentLoop ; then jump
pop ds
pop di
pop si
@@Done:
pop bp
ret
_x_define_mouse_cursor endp
;----------------------------------------------------------------------
; x_show_mouse - Shows a previously hidden mouse cursor
;
; C Prototype
;
; void x_show_mouse()
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_show_mouse proc
push bp
mov bp,sp
cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
je @@Done
cmp [_MouseHidden],FALSE ; If not hidden then exit
je @@Done
push si
push di
@@WaitEndOfHandler: ; Make sure handler not currently active
mov cl,[inhandler]
or cl,cl
jnz @@WaitEndOfHandler
mov si,[_VisiblePageOffs] ; Save mouse background and pos details
mov ax,[_MouseY]
mov bx,[_MouseX]
mov [OldScrnOffs],si
mov [OldY],ax
mov [OldX],bx
call getbg
push [_VisiblePageOffs] ; Draw cursor
push [_ScrnLogicalHeight]
xor ax,ax
push ax
push [OldY]
push [OldX]
call _x_put_cursor
add sp,10
mov [_MouseHidden],FALSE ; Indicate mouse cursor no longer hidden
pop di
pop si
@@Done:
pop bp
ret
_x_show_mouse endp
;----------------------------------------------------------------------
; x_hide_mouse - Hides a previously visible mouse cursor
;
; C Prototype
;
; void x_hide_mouse()
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_hide_mouse proc
push bp
mov bp,sp
cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
je @@Done
cmp [_MouseHidden],FALSE ; If cursor is already hidden exit
jne @@Done
push si
push di
@@WaitEndOfHandler: ; Make sure handler not currently active
mov cl,[inhandler]
or cl,cl
jnz @@WaitEndOfHandler
mov [_MouseHidden],TRUE ; Delete mouse cursor
mov di,[OldScrnOffs]
mov ax,[OldY]
mov bx,[OldX]
call restorebg
pop di
pop si
@@Done:
pop bp
ret
_x_hide_mouse endp
;----------------------------------------------------------------------
; x_remove_mouse - removes mouse handler
;
; C Prototype
;
; void x_remove_mouse()
;
; NOTE: This function MUST be called before quitting the program if
; a mouse handler has been installed
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_mouse_remove proc
push bp
mov bp,sp
cmp [_MouseInstalled],FALSE ; Check whether we have installed
je @@Done ; our mouse handler
call _x_hide_mouse
mov ax,12 ; FUNC 12: Install event handler
xor cx,cx ; Disable all events
int 33h
mov [_MouseInstalled],FALSE
@@Done:
pop bp
ret
_x_mouse_remove endp
;----------------------------------------------------------------------
; x_position_mouse - Positions the mouse cursor at the specified location
;
; C Prototype
;
; void x_position_mouse(int x, int y)
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_position_mouse proc
ARG X:word,Y:word
push bp
mov bp,sp
@@WaitEndOfHandler: ; Make sure handler not currently active
mov bl,[inhandler]
or bl,bl
jnz @@WaitEndOfHandler
mov ax,4
mov cx,X
mov dx,Y
mov [_MouseX],cx
mov [_MouseY],dx
shl cx,1
mov [inhandler],1
int 33h
; The handler doesnt get called so need
; to update manually;
cmp [_MouseHidden],FALSE
jne @@NotVisible
push di si
call update_cursor
pop si di
@@NotVisible:
mov [inhandler],0
pop bp
ret
_x_position_mouse endp
;----------------------------------------------------------------------
; x_update_mouse - Forces the mouse position to be updated and cursor
; to be redrawn.
;
; C Prototype
;
; void x_update_mouse()
;
; Note this function is useful when you have set "MouseFrozen" to true.
; Allows the cursor position to be updated manually rather than
; automatically by the installed handler.
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
_x_update_mouse proc
push bp
mov bp,sp
cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
je @@Done
cmp [_MouseHidden],FALSE ; If cursor is already hidden exit
jne @@Done
push si
push di
mov ax,03h ; FUNC 3: get cursor pos / button status
int 33h ; Update position variables first
shr cx,1
mov [_MouseX],cx
mov [_MouseY],dx
mov [_MouseButtonStatus],bx ; Update button status
call update_cursor
pop di
pop si
@@Done:
pop bp
ret
_x_update_mouse endp
;----------------------------------------------------------------------
; x_put_cursor - Draws the mouse cursor
;
; C Prototype
;
; void x_put_cursor(int X, int Y, int TopClip, int BottomClip, WORD ScrnOffs)
;
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
ALIGN 2
_x_put_cursor proc
ARG X:word,Y:word,TopClip,BottomClip,ScrnOffs
LOCAL Height,TopRow,NextLineIncr:word=LocalStk
push bp
mov bp,sp
sub sp,LocalStk ; Create space for local variables
push si
push di
push ds
mov ax,@data
mov ds,ax
cld
mov ax,14 ; Get image height and save in AX
mov bx,Y
; cx = top Row
;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
mov dx,[TopClip] ; Compare u.l. Y coord with Top
sub dx,bx ; clipping border
jle @@NotTopClip ; jump if not clipped from above
cmp dx,ax
jnl @@NotVisible ; jump if is completely obscured
mov cx,dx
sub ax,dx
add bx,dx
jmp short @@VertClipDone
;;;; EXIT FOR COMPLETELY OBSCURED ;;;;;;;;;;;;;;;;;;;;;;
@@NotVisible:
pop ds
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
@@NotTopClip:
mov dx,[BottomClip]
sub dx,bx
js @@NotVisible
mov cx,0
cmp dx,ax
jg @@VertClipDone
inc dx
mov ax,dx
@@VertClipDone:
mov [Height],ax
mov [TopRow],cx
mov ax,_SCREEN_SEG ; Point es to VGA segment
mov es,ax
mov ax,bx
mov cx,[_ScrnLogicalByteWidth] ; Find required screen address
mul cx
mov di,ax
sub cx,3 ; Distance to next screen row
mov [NextLineIncr],cx
mov cx,[X]
mov bx,cx
shr cx,2
add di,cx
and bx,3
add di,[ScrnOffs]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,42
mul bx
mov si,offset MouseMask
add si,ax
mov ax,3 ; Increment DS:BX and DS:SI to
mul [TopRow] ; been clipped by the top border
add si,ax ; by the L.H.S border
mov dx,SC_INDEX ; Point SC register to map mask
mov al,MAP_MASK ; in preperation for masking data
out dx,al
inc dx ; Point dx to SC data register
mov ah,byte ptr [Height] ; AH = Scanline loop counter
mov bl,[_MouseColor]
@@RowLoop:
mov cx,3 ; Width in bytes across
@@ColLoop:
lodsb ; load plane mask and set MAP MASK
out dx,al
mov es:[di],bl ; store color to specified planes
inc di
loop @@ColLoop
add di,[NextLineIncr]
dec ah
jnz @@RowLoop
pop ds
pop di ; restore registers
pop si
mov sp,bp ; dealloc local variables
pop bp
ret
_x_put_cursor endp
;----------------------------------------------------------------------
; getbg - saves cursor background
;
; C Prototype
;
; local function using register parameters
;
; si = screen offset
; ax = y
; bx = x
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
ALIGN 2
getbg proc near
push bp
mov bp,sp
push ds
cld
mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
mul cx ; width then adding screen offset
add si,ax ; Add Dest Screen Row to di
sub cx,3
shr bx,2
add si,bx
mov bx,cx
mov di,BGSaveOffs
mov ax,_SCREEN_SEG ; Point es to VGA segment
mov es,ax
mov ds,ax
mov dx,GC_INDEX ; Set bit mask for all bits from
mov ax,BIT_MASK ; VGA latches and none from CPU
out dx,ax
mov dx,SC_INDEX ; Point SC register to map mask
mov al,MAP_MASK ; in preperation for masking data
out dx,al
inc dx
mov al,0fh
out dx,al
mov cx,14
@@Loop:
movsb
movsb
movsb
add si,bx
loop @@Loop
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
mov sp,bp ; dealloc local variables
pop bp
ret
getbg endp
;----------------------------------------------------------------------
; restorebg - restores cursor background
;
; C Prototype
;
; local function using register parameters
;
; di = screen offset
; ax = y
; bx = x
;
; Written by Themie Gouthas
;----------------------------------------------------------------------
ALIGN 2
restorebg proc near
;di = scrn offs
;ax = y
;bx = x
push bp
mov bp,sp
push ds
cld
mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
mul cx ; width then adding screen offset
add di,ax ; Add Dest Screen Row to di
sub cx,3
shr bx,2
add di,bx
mov si,BGSaveOffs
mov ax,_SCREEN_SEG ; Point es to VGA segment
mov es,ax
mov ds,ax
mov dx,GC_INDEX ; Set bit mask for all bits from
mov ax,BIT_MASK ; VGA latches and none from CPU
out dx,ax
mov dx,SC_INDEX ; Point SC register to map mask
mov al,MAP_MASK ; in preperation for masking data
out dx,al
inc dx
mov al,0fh
out dx,al
mov bx,cx
mov cx,14
@@Loop:
movsb
movsb
movsb
add di,bx
loop @@Loop
mov dx,GC_INDEX+1 ;restore the bit mask to its default,
mov al,0ffh ; which selects all bits from the CPU
out dx,al ; and none from the latches (the GC
; Index still points to Bit Mask)
pop ds
pop bp
ret
restorebg endp
;********************** The Mouse event handler *************************
ALIGN 2
mouse_handler proc far
push bp
mov bp,sp
push ds
mov di,@data ; Make sure DS points to data segment
mov ds,di
cmp [inhandler],1
jne @@NotActive
pop ds
pop bp
ret
@@NotActive:
mov [inhandler],1
mov [_MouseButtonStatus],bx ; Update button status
test ax,1 ; Is this a motion event ?
jz @@Done ; No Jump
shr cx,1 ; convert X coord to pixel coords
mov [_MouseX],cx ; save mouse position
mov [_MouseY],dx
cmp [_MouseHidden],TRUE ; If mouse hidden dont bother drawing
je @@Done
cmp [_MouseFrozen],TRUE ; If mouse hidden dont bother drawing
je @@Done
call update_cursor
@@Done:
mov [inhandler],0
pop ds
pop bp
ret
mouse_handler endp
end