home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------
- ; 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
- ;-----------------------------------------------------------------------
-
- 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
-
-
- 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 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
-
-
- ;----------------------------------------------------------------------
- ; 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,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_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 ax,4
- mov cx,X
- shl cx,1
- mov dx,Y
- int 33h
- 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
-
- 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,[_ScrnLogicalHeight]
- push ax
- mov ax,0
- push ax
- push [OldY]
- push [OldX]
- call _x_put_cursor
- add sp,10
-
- 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 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 bx,cx
- 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
- LOCAL poschange:word=StkSize
- push bp
- mov bp,sp
- sub sp,StkSize
- push ds
- push si
- push di
- mov ax,@data ; Make sure DS points to data segment
- mov ds,ax
- mov [inhandler],1
- mov [_MouseButtonStatus],bx ; Update button status
- test cx,1 ; Is this a motion event ?
- jnz @@Done ; Yes 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
-
- 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
-
- @@Done:
- mov [inhandler],0
- pop di
- pop si
- pop ds
- mov sp,bp
- pop bp
- ret
- mouse_handler endp
-
-
- end