1 ;-----------------------------------------------------------------------
\r
4 ; Mouse functions functions for all MODE X 256 Color resolutions
\r
9 ; ****** XLIB - Mode X graphics library ****************
\r
10 ; ****** ****************
\r
11 ; ****** Written By Themie Gouthas ****************
\r
13 ; This module is based on Shane Hyde's module of the same name,
\r
14 ; posted to Rec.Games.Programmer, October 92.
\r
17 ; egg@dstos3.dsto.gov.au
\r
18 ; teg@bart.dsto.gov.au
\r
20 ; mouse cursor shape by Tiaan A Geldenhuys
\r
22 ;-----------------------------------------------------------------------
\r
27 This is a module implementing very basic mouse functions.
\r
29 It does not support the full functionality of:
\r
35 --------------------------------------
\r
37 MS Mouse Driver Functions
\r
39 Mouse Initialization 0
\r
42 Get Mouse Position & Button Status 3
\r
43 Set Mouse Cursor Position 4
\r
44 Get Button Press Information 5
\r
45 Get Button Release Information 6
\r
46 Set Min/Max Horizontal Position 7
\r
47 Set Min/Max Vertical Position 8
\r
48 Define Graphics Cursor Block 9
\r
49 Define Text Cursor 10
\r
50 Read Mouse Motion Counters 11
\r
51 Define Event Handler 12
\r
52 Light Pen Emulation Mode ON 13
\r
53 Light Pen Emulation Mode OFF 14
\r
54 Set Mouse Mickey/Pixel Ratio 15
\r
55 Conditional Hide Cursor 16
\r
56 Set Double-Speed Threshold 19
\r
57 --------------------------------------
\r
65 global _MouseInstalled :word
\r
66 global _MouseHidden :word
\r
67 global _MouseButtonStatus :word
\r
68 global _MouseX :word
\r
69 global _MouseY :word
\r
70 global _MouseFrozen :byte
\r
71 global _MouseColor :byte
\r
73 global _x_define_mouse_cursor :proc
\r
74 global _x_show_mouse :proc
\r
75 global _x_hide_mouse :proc
\r
76 global _x_mouse_remove :proc
\r
77 global _x_position_mouse :proc
\r
78 global _x_put_cursor :proc
\r
79 global _x_update_mouse :proc
\r
80 global _x_mouse_init :proc
\r
81 global _x_mouse_window :proc
\r
88 InitMouseDef db 00000001b ; Default mouse mask, note the reverse order
\r
107 Old mouse definition
\r
109 InitMouseDef db 00000001b ; Default mouse mask, note the reverse order
\r
126 MouseMask db 168 dup(?)
\r
128 OldHandlerOffs dw ?
\r
129 OldHandlerMask dw ?
\r
136 _MouseInstalled dw 0 ; Flag indicating whether mouse is installed
\r
137 _MouseHidden dw 0 ; Flag indicating whether mouse is hidden
\r
138 _MouseButtonStatus dw 0 ; Holds current button press information
\r
139 _MouseX dw 0 ; Coords of cursor hot spot
\r
141 _MouseFrozen db 0 ; Mouse motion enable/disable control
\r
142 _MouseColor db 0 ; Mouse cursor colour
\r
147 ;----------------------------------------------------------------------
\r
148 ; Local function that updates the cursor position
\r
150 ; Destroys SI,DI,AX,BX
\r
152 ;----------------------------------------------------------------------
\r
153 proc update_cursor near
\r
156 mov di,[OldScrnOffs] ; Delete cursor (restore old background)
\r
162 mov si,[_VisiblePageOffs] ; Save cursor background
\r
165 mov [OldScrnOffs],si
\r
170 push [_VisiblePageOffs] ; Draw the cursor
\r
171 mov ax,[_ScrnPhysicalHeight]
\r
183 ;----------------------------------------------------------------------
\r
184 ; x_mouse_init - Initialise Mode X mouse handler
\r
188 ; int x_mouse_init()
\r
190 ; This is the first function you must call before using any of the mouse
\r
193 ; WARNING: This function uses and updates "NonVisual_Offset" to allocate
\r
194 ; video ram for the saved mouse background.
\r
196 ; This mouse code uses the fastest possible techniques to save and restore
\r
197 ; mouse backgrounds and to draw the mouse cursor.
\r
199 ; LIMITATIONS: No clipping is supported horizontally for the mouse cursor
\r
200 ; No validity checking is performed for NonVisual_Offs
\r
203 ; **WARNING** Hide or freeze mouse while drawing using any of the other
\r
204 ; Modules. VGA register settings are not preserved which will
\r
205 ; result in unpredictable drawing behavior.
\r
206 ; If you know the drawing will occur away from the mouse cursor
\r
207 ; set MouseFrozen to TRUE (1), do your drawing then set it to
\r
208 ; FALSE (0). Alternatively call "x_hide_mouse", perform your
\r
209 ; drawing and then call "x_show_mouse"
\r
212 ; Written by Themie Gouthas
\r
213 ;----------------------------------------------------------------------
\r
218 cmp [_MouseButtonCount],0 ; Dont initialize if mouse detection
\r
219 jne @@DontInitialize ; or initialization function previously
\r
221 xor ax,ax ; FUNC 0: Mouse Initialization
\r
223 or ax,ax ; Is there a mouse installed ?
\r
225 mov [_MouseButtonCount],bx ; Set the button count
\r
229 mov [_MouseInstalled],ax
\r
230 or ax,ax ; Do we have an installed mouse driver ?
\r
233 mov ax,[_NonVisual_Offs]; ; Allocate VRAM for saved background
\r
237 mov [_NonVisual_Offs],ax ; Update NonVisualOffset
\r
239 mov ax,02 ; FUNC 2: Hide Cursor
\r
240 int 33h ; (hide the mouse driver's default cursor)
\r
241 mov _MouseInstalled,TRUE ; Indicate user mouse driver present
\r
243 mov ax,07h ; FUNC 7:Set min/max horizontal position
\r
245 mov dx,[_ScrnPhysicalPixelWidth]
\r
246 shl dx,1 ; Mult X by 2 as cursor steps by 2 pixels
\r
247 int 33h ; 0 < X < _ScrnPhysicalPixelWidth
\r
249 mov ax,08h ; FUNC 8:Set min/max vertical position
\r
251 mov dx,_ScrnPhysicalHeight
\r
252 int 33h ; 0 < Y < _ScrnPhysicalHeight
\r
254 mov ax,0fh ; FUNC 15: Mouse Hor/Vert resolution
\r
255 mov cx,4 ; Horiz speed >> Value => << Speed
\r
256 mov dx,8 ; Vert Speed
\r
259 mov ax,3 ; FUNC 3: Get mouse pos & button status
\r
265 mov ax,12 ; FUNC 12: Define Event Handler
\r
266 mov bx,seg mouse_handler ; ES:DX -> Event handler
\r
268 mov dx,offset mouse_handler
\r
269 mov cx,1fh ; Set handler for all events
\r
274 mov [_MouseHidden],TRUE ; Mouse initially hidden
\r
276 push ds ; Set the default cursor shape
\r
277 mov ax,offset InitMouseDef
\r
279 call _x_define_mouse_cursor
\r
282 mov ax,[_MouseInstalled] ; Return MouseInstalled flag
\r
288 ;----------------------------------------------------------------------
\r
289 ; x_mouse_window - Define a mouse window
\r
293 ; void x_mouse_window(int x0, int y0, int x1, int y1);
\r
296 ; Written by Themie Gouthas
\r
297 ;----------------------------------------------------------------------
\r
298 _x_mouse_window proc
\r
299 ARG x0:word,y0:word,x1:word,y1:word
\r
303 mov ax,7 ; FUNC 7: Set X range
\r
310 mov ax,8 ; FUNC 8: Set Y range
\r
316 _x_mouse_window endp
\r
319 ;----------------------------------------------------------------------
\r
320 ; x_define_mouse_cursor - Define a mouse cursor from an input bitmask
\r
324 ; void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)
\r
326 ; WARNING: This function assumes MouseDef points to 14 bytes.
\r
328 ; Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..
\r
329 ; bit 0 represents pixel 7 in each "MouseDef" byte.
\r
331 ; Written by Themie Gouthas
\r
332 ;----------------------------------------------------------------------
\r
333 _x_define_mouse_cursor proc
\r
334 ARG MouseDef:dword,MouseColor:byte
\r
338 cmp [_MouseInstalled],FALSE ; Check whether we have installed
\r
339 je @@Done ; our mouse handler and leave if not
\r
341 mov al,[MouseColor] ; Set the mouse pointers color
\r
342 mov [_MouseColor],al
\r
347 mov ax,ds ; ES:DI -> Stored plane mask for all
\r
348 mov es,ax ; pixel alignments of mouse cursor
\r
349 mov di,offset MouseMask
\r
351 xor cl,cl ; CL = current alignment (initially zero)
\r
353 push si ; save MouseDef ptr for next alignment
\r
354 mov dh,14 ; Init Row counter to Cursor Height
\r
356 lodsb ; Load first cursor def byte each bit
\r
357 ; representing pixel in the row
\r
358 xor ah,ah ; AH is the shift overflow byte
\r
359 shl ax,cl ; Shift mask for current alignment
\r
361 mov bl,al ; store first three nibbles of ax into
\r
362 and bl,0fh ; consecutive bytes in the destination
\r
363 mov es:[di],bl ; buffer
\r
368 dec dh ; Next row for this alignment if there
\r
369 jnz @@RowLoop ; are more to do
\r
371 pop si ; point to the start of the cursor def.
\r
372 inc cl ; Select next pixel alignment
\r
373 cmp cl,4 ; If there are more alignments to do
\r
374 jne @@AlignmentLoop ; then jump
\r
382 _x_define_mouse_cursor endp
\r
385 ;----------------------------------------------------------------------
\r
386 ; x_show_mouse - Shows a previously hidden mouse cursor
\r
390 ; void x_show_mouse()
\r
392 ; Written by Themie Gouthas
\r
393 ;----------------------------------------------------------------------
\r
397 cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
\r
399 cmp [_MouseHidden],FALSE ; If not hidden then exit
\r
405 @@WaitEndOfHandler: ; Make sure handler not currently active
\r
408 jnz @@WaitEndOfHandler
\r
411 mov si,[_VisiblePageOffs] ; Save mouse background and pos details
\r
414 mov [OldScrnOffs],si
\r
419 push [_VisiblePageOffs] ; Draw cursor
\r
420 push [_ScrnLogicalHeight]
\r
428 mov [_MouseHidden],FALSE ; Indicate mouse cursor no longer hidden
\r
438 ;----------------------------------------------------------------------
\r
439 ; x_hide_mouse - Hides a previously visible mouse cursor
\r
443 ; void x_hide_mouse()
\r
445 ; Written by Themie Gouthas
\r
446 ;----------------------------------------------------------------------
\r
451 cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
\r
453 cmp [_MouseHidden],FALSE ; If cursor is already hidden exit
\r
458 @@WaitEndOfHandler: ; Make sure handler not currently active
\r
461 jnz @@WaitEndOfHandler
\r
463 mov [_MouseHidden],TRUE ; Delete mouse cursor
\r
464 mov di,[OldScrnOffs]
\r
476 ;----------------------------------------------------------------------
\r
477 ; x_remove_mouse - removes mouse handler
\r
481 ; void x_remove_mouse()
\r
483 ; NOTE: This function MUST be called before quitting the program if
\r
484 ; a mouse handler has been installed
\r
486 ; Written by Themie Gouthas
\r
487 ;----------------------------------------------------------------------
\r
488 _x_mouse_remove proc
\r
491 cmp [_MouseInstalled],FALSE ; Check whether we have installed
\r
492 je @@Done ; our mouse handler
\r
494 mov ax,12 ; FUNC 12: Install event handler
\r
495 xor cx,cx ; Disable all events
\r
497 mov [_MouseInstalled],FALSE
\r
501 _x_mouse_remove endp
\r
504 ;----------------------------------------------------------------------
\r
505 ; x_position_mouse - Positions the mouse cursor at the specified location
\r
509 ; void x_position_mouse(int x, int y)
\r
512 ; Written by Themie Gouthas
\r
513 ;----------------------------------------------------------------------
\r
514 _x_position_mouse proc
\r
519 @@WaitEndOfHandler: ; Make sure handler not currently active
\r
523 jnz @@WaitEndOfHandler
\r
535 ; The handler doesnt get called so need
\r
536 ; to update manually;
\r
538 cmp [_MouseHidden],FALSE
\r
548 _x_position_mouse endp
\r
550 ;----------------------------------------------------------------------
\r
551 ; x_update_mouse - Forces the mouse position to be updated and cursor
\r
556 ; void x_update_mouse()
\r
558 ; Note this function is useful when you have set "MouseFrozen" to true.
\r
559 ; Allows the cursor position to be updated manually rather than
\r
560 ; automatically by the installed handler.
\r
563 ; Written by Themie Gouthas
\r
564 ;----------------------------------------------------------------------
\r
565 _x_update_mouse proc
\r
568 cmp [_MouseInstalled],FALSE ; Make sure our handler is installed
\r
570 cmp [_MouseHidden],FALSE ; If cursor is already hidden exit
\r
574 mov ax,03h ; FUNC 3: get cursor pos / button status
\r
575 int 33h ; Update position variables first
\r
579 mov [_MouseButtonStatus],bx ; Update button status
\r
586 _x_update_mouse endp
\r
589 ;----------------------------------------------------------------------
\r
590 ; x_put_cursor - Draws the mouse cursor
\r
594 ; void x_put_cursor(int X, int Y, int TopClip, int BottomClip, WORD ScrnOffs)
\r
597 ; Written by Themie Gouthas
\r
598 ;----------------------------------------------------------------------
\r
601 ARG X:word,Y:word,TopClip,BottomClip,ScrnOffs
\r
602 LOCAL Height,TopRow,NextLineIncr:word=LocalStk
\r
605 sub sp,LocalStk ; Create space for local variables
\r
613 mov ax,14 ; Get image height and save in AX
\r
617 ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
\r
619 mov dx,[TopClip] ; Compare u.l. Y coord with Top
\r
620 sub dx,bx ; clipping border
\r
621 jle @@NotTopClip ; jump if not clipped from above
\r
623 jnl @@NotVisible ; jump if is completely obscured
\r
627 jmp short @@VertClipDone
\r
629 ;;;; EXIT FOR COMPLETELY OBSCURED ;;;;;;;;;;;;;;;;;;;;;;
\r
633 pop di ; restore registers
\r
635 mov sp,bp ; dealloc local variables
\r
639 ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
642 mov dx,[BottomClip]
\r
656 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
660 mov cx,[_ScrnLogicalByteWidth] ; Find required screen address
\r
664 sub cx,3 ; Distance to next screen row
\r
665 mov [NextLineIncr],cx
\r
675 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
680 mov si,offset MouseMask
\r
683 mov ax,3 ; Increment DS:BX and DS:SI to
\r
684 mul [TopRow] ; been clipped by the top border
\r
685 add si,ax ; by the L.H.S border
\r
687 mov dx,SC_INDEX ; Point SC register to map mask
\r
688 mov al,MAP_MASK ; in preperation for masking data
\r
690 inc dx ; Point dx to SC data register
\r
691 mov ah,byte ptr [Height] ; AH = Scanline loop counter
\r
692 mov bl,[_MouseColor]
\r
694 mov cx,3 ; Width in bytes across
\r
696 lodsb ; load plane mask and set MAP MASK
\r
698 mov es:[di],bl ; store color to specified planes
\r
702 add di,[NextLineIncr]
\r
707 pop di ; restore registers
\r
709 mov sp,bp ; dealloc local variables
\r
715 ;----------------------------------------------------------------------
\r
716 ; getbg - saves cursor background
\r
720 ; local function using register parameters
\r
722 ; si = screen offset
\r
726 ; Written by Themie Gouthas
\r
727 ;----------------------------------------------------------------------
\r
736 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
737 mul cx ; width then adding screen offset
\r
738 add si,ax ; Add Dest Screen Row to di
\r
745 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
749 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
750 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
753 mov dx,SC_INDEX ; Point SC register to map mask
\r
754 mov al,MAP_MASK ; in preperation for masking data
\r
768 mov dx,GC_INDEX+1 ;restore the bit mask to its default,
\r
769 mov al,0ffh ; which selects all bits from the CPU
\r
770 out dx,al ; and none from the latches (the GC
\r
771 ; Index still points to Bit Mask)
\r
774 mov sp,bp ; dealloc local variables
\r
779 ;----------------------------------------------------------------------
\r
780 ; restorebg - restores cursor background
\r
784 ; local function using register parameters
\r
786 ; di = screen offset
\r
790 ; Written by Themie Gouthas
\r
791 ;----------------------------------------------------------------------
\r
793 restorebg proc near
\r
802 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
803 mul cx ; width then adding screen offset
\r
804 add di,ax ; Add Dest Screen Row to di
\r
809 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
813 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
814 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
817 mov dx,SC_INDEX ; Point SC register to map mask
\r
818 mov al,MAP_MASK ; in preperation for masking data
\r
832 mov dx,GC_INDEX+1 ;restore the bit mask to its default,
\r
833 mov al,0ffh ; which selects all bits from the CPU
\r
834 out dx,al ; and none from the latches (the GC
\r
835 ; Index still points to Bit Mask)
\r
843 ;********************** The Mouse event handler *************************
\r
846 mouse_handler proc far
\r
851 mov di,@data ; Make sure DS points to data segment
\r
861 mov [_MouseButtonStatus],bx ; Update button status
\r
862 test ax,1 ; Is this a motion event ?
\r
863 jz @@Done ; No Jump
\r
865 shr cx,1 ; convert X coord to pixel coords
\r
866 mov [_MouseX],cx ; save mouse position
\r
869 cmp [_MouseHidden],TRUE ; If mouse hidden dont bother drawing
\r
872 cmp [_MouseFrozen],TRUE ; If mouse hidden dont bother drawing
\r