; ; 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 . ; ;*************************************************************************** ;** 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 : MOUSE.ASM * ;* * ;* Programmer : Phil W. Gorrow * ;* * ;* Start Date : August 26, 1994 * ;* * ;* Last Update : November 3, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* Install_Mouse -- Initializes mouse driver and verifies mouse exists * ;* Remove_Mouse -- uninstalls the mouse interrupt by disabling the call * ;* Get_Mouse_X -- Returns the mouses x pixel position * ;* Get_Mouse_Y -- Returns the mouse's y pixel position * ;* Get_Mouse_Button -- Gets the values of the mouse button * ;* Set_Mouse_Cursor -- Sets the shape to be used as the mouse. * ;* Low_Hide_Mouse -- Low-level routine which hides the mouse * ;* Low_Show_Mouse -- Low level routine which shows the mouse * ;* Mouse_Shadow_Buffer -- Handles storing and restoring the mouse buffer * ;* Draw_Mouse -- Handles drawing the mouse cursor * ;* Hide_Mouse -- Hides mouse cursor on screen if it was show * ;* Show_Mouse -- Display mouse cursor on screen if it was hidden * ;* Conditional_Hide_Mouse -- Hides mouse if its with given region * ;* Conditional_Show_Mouse -- shows mouse if it was conditionally hidden * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL ; the product runs in ideal mode P386 ; use 386 real mode instructions MODEL USE32 FLAT 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 "keystruc.inc" INCLUDE "shape.inc" include "svgaprim.inc" DOS_SYS_CALL EQU 21h ; to do TNT DOS-XNDR system calls. RESTORE_VISIBLE_PAGE EQU 0 STORE_VISIBLE_PAGE EQU 1 CONDHIDE EQU 08000H ; bit for testing conditional region CONDHIDDEN EQU 04000H ; bit for testing conditional hidden ;--------------------------------------------------------------------------- ; Define any data which needs to be global... ;--------------------------------------------------------------------------- GLOBAL RealModePtr:DWORD GLOBAL MInstalled:DWORD GLOBAL MouseBuffer:DWORD GLOBAL LCW_Uncompress:NEAR GLOBAL Get_Shape_Uncomp_Size :NEAR GLOBAL Get_Shape_Width :NEAR GLOBAL Get_Shape_Original_Height :NEAR GLOBAL Size_Of_Region :NEAR GLOBAL _ShapeBuffer :DWORD GLOBAL XRes : dword GLOBAL YRes : dword GLOBAL VesaFunc : dword GLOBAL Vesa_XRes : near GLOBAL Vesa_YRes : near DPMI_INTR EQU 31h STRUC DPMI_REGS _edi dd ? _esi dd ? _ebp dd ? dd ? _ebx dd ? _edx dd ? _ecx dd ? _eax dd ? Flags dw ? _es dw ? _ds dw ? _fs dw ? _gs dw ? _ip dw ? _cs dw ? _sp dw ? _ss dw ? dd ? dd ? nothing dd ? ENDS ;--------------------------------------------------------------------------- ; Now lets handle any data in the data segment ;--------------------------------------------------------------------------- DATASEG RealInt DPMI_REGS <> ; structure to call a real mode int MInstalled DD 0 ; is the mouse installed? MouseCursor DD 0 MouseBuffer DD 0 BufferWidth DD 0 BufferHeight DD 0 BufferSize DD 0 PrevMousePtr DD 0 MouseBufferSel DD 0 Draw_Mouse dd VGA_Draw_Mouse Mouse_Shadow_Buffer dd VGA_Mouse_Shadow_Buffer ;--------------------------------------------------------------------------- ; Time to write some code ;--------------------------------------------------------------------------- CODESEG ;*************************************************************************** ;* INSTALL_MOUSE -- Initializes mouse driver and verifies mouse connected * ;* * ;* First check the mouse interupt to see if the vector is pointing to zero * ;* page. If it is not then make sure it is not pointing to an IRET. If * ;* not call the mouse reset to verify that the hardware is attached. * ;* * ;* INPUT: int mouse_max_width - the max width of the mouse cursor * ;* int mouse_max_height - the max height of the mouse cursor * ;* int screen_width - width of the physical screen * ;* int screen_height - height of the physical screen * ;* * ;* OUTPUT: TRUE is mouse driver is initialized, FALSE if unable to * ;* initialize mouse driver. * ;* * ;* PROTO: int Install_Mouse( int mouse_max_width, * ;* int mouse_max_height, * ;* int screen_width, * ;* int screen_height); * ;* * ;* HISTORY: * ;* 08/26/1994 PWG : Created. * ;*=========================================================================* GLOBAL Install_Mouse:NEAR PROC Install_Mouse C NEAR USES ebx,ecx,edx,esi,edi ARG mouse_max_width:DWORD ARG mouse_max_height:DWORD ARG screen_width:DWORD ARG screen_height:DWORD ;*=========================================================================* ;* Initialize all of the general mouse variables ;*=========================================================================* mov esi,[RealModePtr] ; get offset of real mode data start test esi , esi ; mouse driver should be install jz ??exit ; after keyboard interrup is install mov eax , [ XRes ] shr eax , 1 mov [(KeyboardType esi).MouseX],eax ; set the mouses x coordinate to 160 mov eax , [ YRes ] shr eax , 1 mov [(KeyboardType esi).MouseY],eax ; set the mouses y coordinate to 100 mov [(KeyboardType esi).MState],1 ; flag the mouse as hidden mov [(KeyboardType esi).MCState],0 ; turn off conditional region mov eax , [ XRes ] mov [(KeyboardType esi).MouseRight],eax mov eax , [ YRes ] mov [(KeyboardType esi).MouseBottom],eax ;========================================================================== ; Get the real mode interrupt vector keyboard ; input ax = 0200, bl = number of interrupt to get ; output cf error, cx,dx= address (seg:off) of RM int handler routine. ; cl set above ;========================================================================== mov eax,0200h mov bl,033h int DPMI_INTR ; do call. jc ??error ; no mouse driver present ;*=========================================================================* ;* If the interupt vector is pointing to 0000:0000h, there is no mouse ;*=========================================================================* mov ax,cx or ax,dx jz short ??nomouse and edx , 0ffffh and ecx , 0ffffh shl ecx,4 add ecx,edx ;*=========================================================================* ;* If the first instruction is an IRET, there is no mouse ;*=========================================================================* cmp [byte ptr ecx],0CFH ; is this an IRET jne short ??mouse_buff ; if it isnt then reset the mouse ??nomouse: mov eax,FALSE ; flag no mouse driver mov [MInstalled],FALSE ; flag no mouse driver jmp ??exit ; exit ??mouse_buff: ;*=========================================================================* ;* Allocate two real mode memory buffers for the mouse cursor and the ;* mouse shadow ;*=========================================================================* mov eax,[mouse_max_width] ; get the is max width mov [BufferWidth],eax ; save it off for set cursor mov edx,[mouse_max_height] ; get the max height mov [BufferHeight],edx ; save it off for set cursor mul edx ; size = max_width * max_height add eax,22 ; add width/height(8) + para align(15) and al, 0f0h ; now size is even paragraphs mov [BufferSize],eax ; store off the buffer size shl eax,1 ; make two of them mov ebx,eax ; get size of RM binary. mov ecx,eax ; ecx will use it later. add ebx,15 ; round up shr ebx,4 ; convert to pages. mov eax,0100h ; alloc real buffer int DPMI_INTR ; do call. jc ??error ; check for error. mov esi,[RealModePtr] ; get offset of real mode data start mov [MouseBufferSel], edx shl eax , 16 mov [(KeyboardType esi).MouseCursor],eax ; store off the real mode segment mov edx,eax ; get the buffer position add edx,[BufferSize] ; add in the buffer size mov [(KeyboardType esi).MouseBuffer],edx ; store off the real mode segment shr eax,12 ; convert the seg/off to 32 bit offset mov edx,eax add edx,[BufferSize] mov [MouseCursor],eax ; store it off in the mouse buffer mov [MouseBuffer],edx ; store it off in the mouse buffer mov eax,0600h ; function number. mov ecx,[MouseCursor] ; ecx must have start of memory. mov edi,[BufferSize] shl edi,1 shld ebx,ecx,16 shld esi,edi,16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. ??begin: mov esi,[RealModePtr] ; get offset of real mode data start ; Reset mouse thru int 33h funtion 0 call Clear_RM_regs mov eax , 0300h mov ebx , 033h xor ecx , ecx mov [RealInt . _eax ] , 0 lea edi, [RealInt] int DPMI_INTR mov eax ,[RealInt . _eax] cmp ax,-1 ; was the mouse attached to system jne ??nomouse ; if not exit out of the routine mov [(KeyboardType esi).Adjust],0 ; assume we do not need to adjust mouse ;*************************************************************************** ; Set the Vesa Parameters mov eax , [ VesaFunc ] test eax , eax jz ??set_vga_mouse mov [(KeyboardType esi). VesaPtr ] , eax mov ax , [(KeyboardType esi). VESAMouseShadow ] mov [(KeyboardType esi). ShadowPtr] , ax mov ax , [(KeyboardType esi). VESAMouseDraw ] mov [(KeyboardType esi). DrawMousePtr ] , ax lea eax , [ VESA_Draw_Mouse ] mov [ Draw_Mouse ] , eax lea eax , [ VESA_Mouse_Shadow_Buffer ] mov [ Mouse_Shadow_Buffer ] , eax mov eax , [ XRes ] mov [(KeyboardType esi). MouseRight ] , eax mov eax , [ YRes ] mov [(KeyboardType esi). MouseBottom ] , eax lea edi , [(KeyboardType esi). VesaBankTable] lea esi , [ BankTable ] mov ecx , 8 rep movsd mov esi,[RealModePtr] ; get offset of real mode data start jmp ??end_vesa ??set_vga_mouse: mov ax , [(KeyboardType esi). VGAMouseShadow ] mov [(KeyboardType esi). ShadowPtr] , ax mov ax , [(KeyboardType esi). VGAMouseDraw ] mov [(KeyboardType esi). DrawMousePtr ] , ax lea eax , [ VGA_Draw_Mouse ] mov [ Draw_Mouse ] , eax lea eax , [ VGA_Mouse_Shadow_Buffer ] mov [ Mouse_Shadow_Buffer ] , eax ??end_vesa: call Reset_Mouse mov eax , TRUE ret ??error: mov eax,FALSE ??exit: ret ENDP Install_Mouse ;*************************************************************************** ;* ResET_MOUSE -- Reset mouse to a new graphif mode * ;* * ;* reset mouse driver funtions to a a currently graphic mode * ;* * ;* INPUT: * ;* OUTPUT: * ;* PROTO: Reset_Mouse ( void ) * ;* * ;* * ;* HISTORY: * ;* 08/26/1994 JRJ : Created. * ;*=========================================================================* GLOBAL Reset_Mouse:NEAR PROC Reset_Mouse C NEAR USES eax,ebx,ecx,edx,esi,edi ;*=========================================================================* ;* Initialize all of the general mouse variables ;*=========================================================================* mov esi , [RealModePtr] ; get offset of real mode data start test esi , esi jz ??exit mov eax , [ XRes ] shr eax , 1 mov [(KeyboardType esi).MouseX],eax ; set the mouses x coordinate to 160 mov eax , [ YRes ] shr eax , 1 mov [(KeyboardType esi).MouseY],eax ; set the mouses y coordinate to 100 mov [(KeyboardType esi).MState],1 ; flag the mouse as hidden mov [(KeyboardType esi).MCState],0 ; turn off conditional region mov eax , [ XRes ] mov [(KeyboardType esi).MouseRight],eax mov eax , [ YRes ] mov [(KeyboardType esi).MouseBottom],eax mov [(KeyboardType esi).Adjust],0 ; assume we do not need to adjust mouse ;*************************************************************************** ; Set the Vesa Parameters mov eax , [ VesaFunc ] test eax , eax jz ??set_vga_mouse mov [(KeyboardType esi). VesaPtr ] , eax mov ax , [(KeyboardType esi). VESAMouseShadow ] mov [(KeyboardType esi). ShadowPtr] , ax mov ax , [(KeyboardType esi). VESAMouseDraw ] mov [(KeyboardType esi). DrawMousePtr ] , ax lea eax , [ VESA_Draw_Mouse ] mov [ Draw_Mouse ] , eax lea eax , [ VESA_Mouse_Shadow_Buffer ] mov [ Mouse_Shadow_Buffer ] , eax mov eax , [ XRes ] mov [(KeyboardType esi). MouseRight ] , eax mov eax , [ YRes ] mov [(KeyboardType esi). MouseBottom ] , eax lea edi , [(KeyboardType esi). VesaBankTable] lea esi , [ BankTable ] mov ecx , 8 rep movsd mov esi,[RealModePtr] ; get offset of real mode data start jmp ??end_vesa ??set_vga_mouse: mov ax , [(KeyboardType esi). VGAMouseShadow ] mov [(KeyboardType esi). ShadowPtr] , ax mov ax , [(KeyboardType esi). VGAMouseDraw ] mov [(KeyboardType esi). DrawMousePtr ] , ax lea eax , [ VGA_Draw_Mouse ] mov [ Draw_Mouse ] , eax lea eax , [ VGA_Mouse_Shadow_Buffer ] mov [ Mouse_Shadow_Buffer ] , eax ??end_vesa: ; S Mickey/pixel Ratio cursor limits call Clear_RM_regs mov eax , 0300h mov ebx , 033h mov ecx , 8 mov edx , 16 mov [RealInt . _eax ] , 0fh mov [RealInt . _ecx] , ecx mov [RealInt . _edx] , edx xor ecx , ecx lea edi, [RealInt] int DPMI_INTR ; Set Min/Max X pos call Clear_RM_regs mov eax , 0300h mov ebx , 033h mov ecx , 0 mov edx , [ XRes ] cmp edx , 320 jne ??set_it shl edx , 1 mov [(KeyboardType esi).Adjust],1 ??set_it: ; dec edx mov [RealInt . _eax ] , 7 mov [RealInt . _ecx] , ecx mov [RealInt . _edx] , edx xor ecx , ecx lea edi, [RealInt] int DPMI_INTR ; Set Min/Max Y pos call Clear_RM_regs mov eax , 0300h mov ebx , 033h mov ecx , 0 mov edx , [ YRes ] dec edx mov [RealInt . _eax ] , 8 mov [RealInt . _ecx] , ecx mov [RealInt . _edx] , edx xor ecx , ecx lea edi, [RealInt] int DPMI_INTR IF 0 ; Check for scale factors in X and Y pos call Clear_RM_regs mov eax , 0300h mov ebx , 033h mov ecx , [ XRes ] mov edx , [ YRes ] sub ecx , 8 sub edx , 16 mov [RealInt . _eax ] , 4 mov [RealInt . _ecx] , ecx mov [RealInt . _edx] , edx xor ecx , ecx lea edi, [RealInt] int DPMI_INTR ; Read mouse position thru int 33 funtion 3 call Clear_RM_regs mov eax , 0300h mov ebx , 033h xor ecx , ecx mov [RealInt . _eax ] , 3 lea edi, [RealInt] int DPMI_INTR mov ecx ,[RealInt . _ecx] mov edx ,[RealInt . _edx] ; compute Scale values X Y for different vendor mouse driver if nessesary add ecx , 8 add edx , 16 cmp ecx , [ XRes ] mov [(KeyboardType esi).Adjust_XPos],0 jz ??No_scaleX mov [(KeyboardType esi).Adjust_XPos],ecx ??No_scaleX: cmp edx , [ YRes ] mov [(KeyboardType esi).Adjust_YPos],0 jz ??No_scaleY mov [(KeyboardType esi).Adjust_YPos],edx ??No_scaleY: ENDIF mov ecx, [ XRes ] ; set the mouses x coordinate to 160 mov edx, [ YRes ] ; set the mouses x coordinate to 160 cmp [(KeyboardType esi).Adjust],1 je ??no_ecx_shift shr ecx , 1 ??no_ecx_shift: shr edx , 1 mov [MInstalled],TRUE ; set the fact that mouse is installed mov [(KeyboardType esi).MDisabled],TRUE ; disable mouse until the overlay is loaded ; Set new Mouse position any way call Clear_RM_regs mov eax , 0300h mov ebx , 033h mov [RealInt . _eax ] , 4 mov [RealInt . _ecx] , ecx mov [RealInt . _edx] , edx xor ecx , ecx lea edi, [RealInt] int DPMI_INTR call Clear_RM_regs mov eax, 0300h mov ebx ,33h ; mouse is in 33h mov ecx,0 ; any mouse condition generates int mov edx,[RealModePtr] ; get real mode memory address shr edx,4 ; convert it to a segment mov [RealInt. _es],dx ; store it in the real mode es movzx edx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code mov [RealInt._edx],edx ; set edx to offset of code mov [RealInt._eax],12 ; set eax to set interrupt routine mov [RealInt._ecx],31 lea edi, [RealInt] int DPMI_INTR ??installed: mov eax,TRUE ; return TRUE if all is well mov [(KeyboardType esi).MDisabled],FALSE ; no 32 bit overlays installed je ??exit ??error: mov eax,FALSE ??exit: ret ENDP Reset_Mouse ;*************************************************************************** ;* REMOVE_MOUSE -- uninstalls the mouse interrupt by disabling the call * ;* * ;* This routine will uninstall the mouse interrupt. It does this by * ;* simply disabling the call condition. The interrupt itself is still * ;* present, just uncalled until dos removes it at program termination. * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: VOID Remove_Mouse(VOID); * ;* * ;* HISTORY: * ;* 08/29/1994 PWG : Created. * ;*=========================================================================* GLOBAL Remove_Mouse:NEAR PROC Remove_Mouse C NEAR USES eax,ebx,ecx,edx,esi,edi call Clear_RM_regs cmp [MInstalled],FALSE ; check to see if mouse installed je ??exit ; if not then no need to remove it mov [MInstalled],FALSE ; Force to NOT-Installed. ;;PWG cmp [_MSWIFTDevice],1 ; check to see if SWIFT device installed ;;PWG je short ??prevSWIFT ; if so use previous SWIFT event handler mov ebx , 033h mov edx,[RealModePtr] ; get real mode memory address test edx,edx ; check that the memory block is valid jz ??exit shr edx,4 ; convert it to a segment mov [RealInt._es],dx ; store it in the real mode es xor edx,edx mov esi,[RealModePtr] ; get offset of real mode data start mov dx,[(KeyboardType PTR esi).MouseCodeOffset] ; Get address of code mov [RealInt._edx],edx ; set edx to offset of code mov [RealInt._eax],12 ; set eax to set interrupt routine mov [RealInt._ecx],0 mov ecx,0 ; no mouse condition generates an int mov eax,0300h lea edi,[RealInt] int DPMI_INTR mov eax,0601h ; function number. mov ecx,[MouseCursor] ; ecx must have start of memory. mov edi,[BufferSize] shl edi,1 shld ebx,ecx,16 shld esi,edi,16 int DPMI_INTR ; do call. ; Deallocate real memory buffer mov edx ,[MouseBufferSel] test dx ,dx jz ??exit mov eax ,0101h int DPMI_INTR ??exit: ret ENDP Remove_Mouse ;*************************************************************************** GLOBAL Clear_RM_regs :NEAR PROC Clear_RM_regs NEAR push eax push ecx push edi lea edi , [ RealInt ] lea ecx , [ RealInt . nothing ] sub ecx , edi xor eax , eax shr ecx , 2 rep stosd pop edi pop ecx pop eax ret ENDP Clear_RM_regs ;*************************************************************************** ;* GET_MOUSE_X -- Returns the mouses x pixel position * ;* * ;* * ;* * ;* INPUT: none * ;* * ;* OUTPUT: int - the mouse x position in pixels * ;* * ;* WARNINGS: int Get_Mouse_X(void); * ;* * ;* HISTORY: * ;* 08/29/1994 PWG : Created. * ;*=========================================================================* GLOBAL Get_Mouse_X:NEAR PROC Get_Mouse_X C NEAR USES esi mov esi,[RealModePtr] mov eax,[(KeyboardType esi).MouseX] ret ENDP Get_Mouse_X ;*************************************************************************** ;* GET_MOUSE_STATE -- Returns the current mouse state * ;* * ;* * ;* * ;* INPUT: none * ;* * ;* OUTPUT: int - the mouse's current state * ;* * ;* WARNINGS: int Get_Mouse_State(void); * ;* * ;* HISTORY: * ;* 08/29/1994 PWG : Created. * ;*=========================================================================* GLOBAL Get_Mouse_State:NEAR PROC Get_Mouse_State C NEAR USES esi mov esi,[RealModePtr] mov eax,[(KeyboardType esi).MState] ret ENDP Get_Mouse_State ;*************************************************************************** ;* GET_MOUSE_X -- Returns the mouses x pixel position * ;* * ;* * ;* * ;* INPUT: none * ;* * ;* OUTPUT: int - the mouse x position in pixels * ;* * ;* WARNINGS: int Get_Mouse_X(void); * ;* * ;* HISTORY: * ;* 08/29/1994 PWG : Created. * ;*=========================================================================* GLOBAL Get_Mouse_Disabled:NEAR PROC Get_Mouse_Disabled C NEAR USES esi mov esi,[RealModePtr] movzx eax,[(KeyboardType esi).MDisabled] ret ENDP Get_Mouse_Disabled ;*************************************************************************** ;* GET_MOUSE_Y -- Returns the mouse's y pixel position * ;* * ;* * ;* * ;* INPUT: none * ;* * ;* OUTPUT: int - the mouses y position in pixels * ;* * ;* PROTO: int Get_Mouse_Y(void); * ;* * ;* HISTORY: * ;* 08/29/1994 PWG : Created. * ;*=========================================================================* GLOBAL Get_Mouse_Y:NEAR PROC Get_Mouse_Y C NEAR USES esi mov esi,[RealModePtr] mov eax,[(KeyboardType esi).MouseY] ret ENDP Get_Mouse_Y ;*************************************************************************** ;* GET_MOUSE_BUTTON -- Gets the values of the mouse button * ;* * ;* * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* PROTO: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 09/19/1994 PWG : Created. * ;*=========================================================================* GLOBAL Get_Mouse_Button:NEAR PROC Get_Mouse_Button C NEAR USES eax,esi mov esi,[RealModePtr] xor eax,eax mov al,[(KeyboardType esi).Button] ret ENDP Get_Mouse_Button ;*************************************************************************** ;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse. * ;* * ;* This will inform the system of the shape desired as the mouse * ;* cursor. * ;* * ;* INPUT: xhotspot -- Offset of click point into shape. * ;* * ;* yhotspot -- Offset of click point into shape. * ;* * ;* cursor -- Shape to use as the new mouse shape. * ;* * ;* OUTPUT: Returns with a pointer to the original mouse shape. * ;* * ;* PROTO: VOID *Set_Mouse_Cursor( int xhotspot, * ;* int yhotspot, * ;* void *cursor); * ;* * ;* HISTORY: * ;* 02/13/1992 JLB : Created. * ;*=========================================================================* GLOBAL Set_Mouse_Cursor:NEAR PROC Set_Mouse_Cursor C NEAR USES ebx,ecx,edx,esi,edi ARG xhotspot:DWORD ; the x hot spot of the mouse ARG yhotspot:DWORD ; the y hot spot of the mouse ARG cursor:DWORD ; ptr to the new mouse cursor LOCAL datasize:DWORD LOCAL stype:WORD LOCAL swidth:DWORD ; Shape width. LOCAL sheight:DWORD ; Shape height. LOCAL ssize:DWORD ; Size of raw shape. ;*=========================================================================* ; Direction flag must be forward in this routine. ;*=========================================================================* cld mov esi,[RealModePtr] ; get offset of real mode data start ;------------------------------------------------------------------- ; Make sure the mouse is Enabled and Installed before continuing ;------------------------------------------------------------------- mov eax,[cursor] cmp eax,0 ; if the mouse cursor is in zero page je ??exit ; it is completely invalid cmp eax,[PrevMousePtr] je ??exit cmp [(KeyboardType esi).MDisabled],FALSE ; make sure the mouse is not disabled jne ??exit ; if it is not then give it a try ;------------------------------------------------------------------- ; We need to wait if a mouse interrupt is in progress. Once the ; interrupt is finished flag that it is occuring so that it will ; not attempt to draw the mouse while we are changing the cursor. ;------------------------------------------------------------------- ??try: inc [(KeyboardType esi).MouseUpdate] ; flag that mouse can not be drawn ;------------------------------------------------------------------- ; If the mouse is currently on the screen hide it. ;------------------------------------------------------------------- call Low_Hide_Mouse ;------------------------------------------------------------------- ; Calculate the size of the buffer needed. ;------------------------------------------------------------------- push [cursor] call Get_Shape_Uncomp_Size pop edx mov [datasize],eax push [cursor] call Get_Shape_Width pop edx mov [swidth],eax cmp eax,[BufferWidth] jg ??end push [cursor] call Get_Shape_Original_Height pop edx mov [sheight],eax cmp eax,[BufferHeight] jg ??end mov ebx,[sheight] mov eax,[swidth] imul ebx,eax ??copy_mouse: mov esi,[cursor] ; set esi to point to mouse shape mov ax,[esi] ; get the shape type byte mov [stype],ax ; save off the shape type test ax,MAKESHAPE_NOCOMP ; is it marked as no compression? je ??comp_shape ; if not go to the comped shape code mov edi,[MouseCursor] ; set edi to point to mouse buffer ??copy_type: test [stype],MAKESHAPE_COMPACT ; if the shape a 16 color shape? jne ??16_color_copy ; if it is then go handle it ??normal_copy: ;------------------------------------------------------------------- ;* Uncompressed NORMAL shapes just get run-length uncompressed ;------------------------------------------------------------------- add esi,10 ; adjust past header of shape mov eax,[swidth] ; load up the width mul [sheight] ; find size of shape in pixels mov edx,eax ; save this in number of bytes xor ecx,ecx ; clear high of loop variable ??norm_unrle: mov al,[esi] ; get a byte out of the file inc esi ; increment to the next pos or al,al ; set the flags on register state jz ??norm_trans ; if its a zero its transparent mov [edi],al ; write out the pixel to dest inc edi ; move to next dest position dec edx ; we have now written another pix jnz ??norm_unrle ; if more to write then do it jmp ??done_copy ; otherwise we are all done ??norm_trans: mov cl,[esi] ; get how many zeros to write sub edx,ecx inc esi ; increment the source position xor al,al ; clear out al cuz we're writing zeros rep stosb ; write all of them out or edx,edx jnz ??norm_unrle ; if more to do then do it jmp ??done_copy ; otherwise we are done ??16_color_copy: ;------------------------------------------------------------------- ;* Uncompressed 16 color shapes just get remaped and UN-RLE'd ;------------------------------------------------------------------- add esi,10 ; adjust past header of shape mov ebx,esi ; save of position of remap add esi,16 ; move past remap table mov eax,[swidth] ; load up the width mul [sheight] ; load up the height mov edx,eax ; save this in number of bytes xor eax,eax ; clear high of lookup variable xor ecx,ecx ; clear high of loop variable ??16_color_unrle: mov al,[esi] ; get a byte out of the file inc esi ; increment to the next pos or al,al ; set the flags on register state jz ??16_color_trans ; if its a zero its transparent mov al,[ebx+eax] ; remap the pixel from 16 color table mov [edi],al ; store it out to the dest address inc edi ; move to next dest address dec edx ; we have now written a pixel jnz ??16_color_unrle jmp ??done_copy ??16_color_trans: mov cl,[esi] ; get how many zeros to write sub edx,ecx ; subtract off count ahead of time inc esi ; increment the source position xor al,al ; clear out al cuz we're writing zeros rep stosb ; write all of them out or edx,edx ; or edx to test for zero jnz ??16_color_unrle jmp ??done_copy ;------------------------------------------------------------------- ; Deal with the compressed shape by copying it into the shape ; staging buffer. ;------------------------------------------------------------------- ??comp_shape: mov edi,[_ShapeBuffer] ; get a pointer to ShapeBuffer mov ax,[esi] ; load in the shape type add esi,2 ; increment the shape pointer or ax,MAKESHAPE_NOCOMP ; make the shape as uncompressed mov [stype],ax ; save off the shape type mov [edi],ax ; write out uncompressed shape add edi,2 ;------------------------------------------------------------------- ; Process the shape header information and copy it over to the new ; location. ;------------------------------------------------------------------- mov ecx,4 ; transfer height, width, org and test eax,MAKESHAPE_COMPACT ; is it a 16 color shape? je ??copy_head ; no - don't worry about it add ecx,8 ; otherwise adjust ecx for header ??copy_head: rep movsw ; copy the necessary bytes mov eax,[datasize] ; get uncompressed length push eax ; push as third param push edi ; push the destination offset push esi ; push the source offset call LCW_Uncompress ; do the uncompress pop eax pop eax pop eax mov esi,[_ShapeBuffer] mov edi,[MouseCursor] ; set edi to point to mouse buffer jmp ??copy_type ??done_copy: mov esi,[RealModePtr] ; get offset of real mode data start mov eax,[xhotspot] ; get the mouse cursors x hotspot mov [(KeyboardType esi).MouseXHot],eax mov eax,[yhotspot] ; get the mouse cursors y hotspot mov [(KeyboardType esi).MouseYHot],eax mov ebx,[sheight] ; get shape height mov [(KeyboardType esi).MouseHeight],ebx mov ebx,[swidth] mov [(KeyboardType esi).MouseWidth],ebx ??error: call Low_Show_Mouse ;------------------------------------------------------------------- ; Final cleanup and exit. ;------------------------------------------------------------------- ??end: dec [(KeyboardType esi).MouseUpdate] ; we are done modifying the cursor ??exit: push [cursor] push [PrevMousePtr] pop eax pop [PrevMousePtr] ret ; and return back to the world ENDP Set_Mouse_Cursor ;*************************************************************************** ;* LOW_HIDE_MOUSE -- Low-level routine which hides the mouse * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 09/19/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Low_Hide_Mouse:NEAR PROC Low_Hide_Mouse C NEAR USES eax,ebx,esi mov ebx,[RealModePtr] ; get 32 bit offset of dos data ;*=========================================================================* ;* Is the mouse disabled or hidden? ;*=========================================================================* cmp [(KeyboardType ebx).MDisabled],0 ; is the mouse disabled? jne short ??end cmp [(KeyboardType ebx).MState],0 ; is the mouse hidden? jne short ??endnodraw ; no need to hide again ;*=========================================================================* ;* Take care of restoring the mouse cursor ;*=========================================================================* mov eax,RESTORE_VISIBLE_PAGE push eax call [ Mouse_Shadow_Buffer] pop eax ;*=========================================================================* ;* The mouse is now hidden -- again. ;*=========================================================================* ??endnodraw: add [(KeyboardType ebx).MState],1 adc [(KeyboardType ebx).MState],0 ??end: ret ENDP Low_Hide_Mouse ;*************************************************************************** ;* LOW_SHOW_MOUSE -- Low level routine which shows the mouse * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 09/19/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Low_Show_Mouse:NEAR PROC Low_Show_Mouse C NEAR USES eax,ebx,ecx,edx,edi,esi LOCAL mousex:DWORD LOCAL mousey:DWORD mov esi,[RealModePtr] ; get offset of real mode data start ;*=========================================================================* ;* Don't show the mouse if it is not hidden or it is disabled ;*=========================================================================* cmp [(KeyboardType esi).MDisabled],0 ; is the mouse disabled jne ??exit ; if so then exit cmp [(KeyboardType esi).MState],0 ; is the mouse already visible je ??exit ; if so then exit ;*=========================================================================* ;* Don't show the mouse if it was hidden multiple times ;*=========================================================================* dec [(KeyboardType esi).MState] ; show the mouse one level cmp [(KeyboardType esi).MState],0 ; can the mouse be shown jne short ??exit ;*=========================================================================* ;* Determine the theoretcial drawing position of the mouse ;*=========================================================================* mov ecx,[(KeyboardType esi).MouseWidth] ; Theoretical buffer width (pixel). mov edx,[(KeyboardType esi).MouseHeight] ; Theoretical buffer height (pixel). mov eax,[(KeyboardType esi).MouseX] mov [mousex],eax ; Draw X pixel. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ebx,[(KeyboardType esi).MouseY] mov [mousey],ebx ; Draw Y pixel. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;*=========================================================================* ;* Determine the theoretical coordinates and dimensions of the ;* area the mouse shape will be rendered upon. ;*=========================================================================* mov [(KeyboardType esi).MouseBuffX],eax mov [(KeyboardType esi).MouseBuffY],ebx mov [(KeyboardType esi).MouseBuffW],ecx mov [(KeyboardType esi).MouseBuffH],edx ;------ Move the area that will be drawn upon, to the graphic buffer. mov eax,STORE_VISIBLE_PAGE push eax call [ Mouse_Shadow_Buffer ] pop eax ;------ Draw the mouse shape to the seenpage. push [mousey] push [mousex] call [ Draw_Mouse ] pop eax pop eax ??exit: ret ENDP Low_Show_Mouse ;*************************************************************************** ;* HIDE_MOUSE -- Hides mouse cursor on screen if it was show * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: void Hide_Mouse(void); * ;* * ;* HISTORY: * ;* 11/03/1994 PWG : Created. * ;*=========================================================================* GLOBAL Hide_Mouse:NEAR PROC Hide_Mouse C NEAR USES eax,esi mov esi,[RealModePtr] ; get the real mode offset ;*=========================================================================* ;* Mark us as updating the mouse and then run and do the update ;*=========================================================================* inc [(KeyboardType esi).MouseUpdate] ; were drawing the mouse call Low_Hide_Mouse ; make the function call dec [(KeyboardType esi).MouseUpdate] ; were done drawing mouse ret ENDP Hide_Mouse ;---------------------------------------------------------------------------- ;*************************************************************************** ;* SHOW_MOUSE -- Display mouse cursor on screen if it was hidden * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: void Show_Mouse(void) * ;* * ;* HISTORY: * ;* 11/03/1994 PWG : Created. * ;*=========================================================================* GLOBAL Show_Mouse:NEAR PROC Show_Mouse C NEAR USES eax,esi mov esi,[RealModePtr] ; get the real mode offset ;*=========================================================================* ;* Mark us as updating the mouse and then run and do the update ;*=========================================================================* inc [(KeyboardType esi).MouseUpdate] ; were drawing the mouse call Low_Show_Mouse ; make the function call dec [(KeyboardType esi).MouseUpdate] ; were done drawing mouse ret ENDP Show_Mouse ;*************************************************************************** ;* CONDITIONAL_HIDE_MOUSE -- Hides mouse if its with given region * ;* * ;* INPUT: int sx_pixel - the left-most pixel position of the region * ;* int sy_pixel - the upper-most pixel position of the region * ;* int dx_pixel - the right most pixel position of the region * ;* int dy_pixel - the lower most pixel position of the region * ;* * ;* OUTPUT: none * ;* * ;* PROTO: void Conditional_Hide_Mouse( int sx_pixel, * ;* int sy_pixel, * ;* int dx_pixel, * ;* int dy_pixel); * ;* * ;* HISTORY: * ;* 11/03/1994 PWG : Created. * ;*=========================================================================* GLOBAL Conditional_Hide_Mouse:NEAR PROC Conditional_Hide_Mouse C NEAR USES eax,ebx,ecx,edx,esi,edi ARG sx_pixel:DWORD ; left x pixel pos ARG sy_pixel:DWORD ; upper y pixel pos ARG dx_pixel:DWORD ; right x pixel pos ARG dy_pixel:DWORD ; lower y pixel pos mov esi,[RealModePtr] ; get the real mode offset ;*=========================================================================* ;* Widen region leftward by amount mouse shape spills to the right of ;* its hot point. Limited to the left edge of the screen. ;*=========================================================================* mov eax,[(KeyboardType esi).MouseWidth] sub eax,[(KeyboardType esi).MouseXHot] neg eax add eax,[sx_pixel] jns short ??noleftlimit xor eax,eax ??noleftlimit: ;*=========================================================================* ;* Widen region upward by amount mouse shape spills below the ;* mouse's hot point. Limited by the top edge of the screen. ;*=========================================================================* mov ebx,[(KeyboardType esi).MouseHeight] sub ebx,[(KeyboardType esi).MouseYHot] neg ebx add ebx,[sy_pixel] jns short ??notoplimit xor ebx,ebx ??notoplimit: ;*=========================================================================* ;* Widen region rightward by amount mouse shape spills to the ;* left of its hot point. Limited by the right edge of the ;* screen. ;*=========================================================================* mov ecx,[dx_pixel] add ecx,[(KeyboardType esi).MouseXHot] cmp ecx,[(KeyboardType esi).MouseRight] jb short ??norightlimit mov ecx,[(KeyboardType esi).MouseRight] dec ecx ??norightlimit: ;*=========================================================================* ;* Widen region downward by amout the mouse shape extends above ;* its hot point. Limited to the bottom of the screen. ;*=========================================================================* mov edx,[dy_pixel] add edx,[(KeyboardType esi).MouseYHot] cmp edx,[(KeyboardType esi).MouseBottom] jb short ??nobottomlimit mov edx,[(KeyboardType esi).MouseBottom] dec edx ??nobottomlimit: inc [(KeyboardType esi).MouseUpdate] ; don't let interrupt scrag variables ;*=========================================================================* ;* The mouse could be in one of four conditions. ;* 1) The mouse is visible and no conditional hide has been specified. ;* (perform normal region checking with possible hide) ;* 2) The mouse is hidden and no conditional hide as been specified. ;* (record region and do nothing) ;* 3) The mouse is visible and a conditional region has been specified ;* (expand region and perform check with possible hide). ;* 4) The mouse is already hidden by a previous conditional. ;* (expand region and do nothing) ;* ;* First: Set or expand the region according to the specified parameters ;*=========================================================================* cmp [(KeyboardType esi).MCState],0 jne short ??expand mov [(KeyboardType esi).MouseCXLeft],eax mov [(KeyboardType esi).MouseCYUpper],ebx mov [(KeyboardType esi).MouseCXRight],ecx mov [(KeyboardType esi).MouseCYLower],edx jmp ??noylower ??expand: ;*=========================================================================* ;* Expand the clipping rectangle. ;*=========================================================================* cmp eax,[(KeyboardType esi).MouseCXLeft] jb short ??noxleft mov [(KeyboardType esi).MouseCXLeft],eax ??noxleft: cmp ebx,[(KeyboardType esi).MouseCYUpper] jb short ??noyupper mov [(KeyboardType esi).MouseCYUpper],ebx ??noyupper: cmp ecx,[(KeyboardType esi).MouseCXRight] ja short ??noxright mov [(KeyboardType esi).MouseCXRight],ecx ??noxright: cmp edx,[(KeyboardType esi).MouseCYLower] ja short ??noylower mov [(KeyboardType esi).MouseCYLower],edx ??noylower: ;*=========================================================================* ;* If the mouse isn't already hidden, then check its location against ;* the hiding region and hide if necessary. ;*=========================================================================* test [(KeyboardType esi).MCState],CONDHIDDEN jne short ??nohide mov eax,[(KeyboardType esi).MouseX] mov ebx,[(KeyboardType esi).MouseY] cmp eax,[(KeyboardType esi).MouseCXLeft] jb short ??nohide cmp eax,[(KeyboardType esi).MouseCXRight] ja short ??nohide cmp ebx,[(KeyboardType esi).MouseCYUpper] jb short ??nohide cmp ebx,[(KeyboardType esi).MouseCYLower] ja short ??nohide ;*=========================================================================* ;* The mouse falls within the region for hiding, so hide it. ;*=========================================================================* call Low_Hide_Mouse ; make the function call or [(KeyboardType esi).MCState],CONDHIDDEN ??nohide: ;*=========================================================================* ;* Record the fact that a Conditional_Hide_Mouse was ;* called and then exit. ;*=========================================================================* or [(KeyboardType esi).MCState],CONDHIDE add [BYTE PTR (KeyboardType esi).MCState],1 adc [BYTE PTR (KeyboardType esi).MCState],0 dec [(KeyboardType esi).MouseUpdate] ret ENDP Conditional_Hide_Mouse ;*************************************************************************** ;* CONDITIONAL_SHOW_MOUSE -- shows mouse if it was conditionally hidden * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: void Conditional_Show_Mouse(void); * ;* * ;* HISTORY: * ;* 11/03/1994 PWG : Created. * ;*=========================================================================* GLOBAL Conditional_Show_Mouse:NEAR PROC Conditional_Show_Mouse C NEAR USES eax,esi mov esi,[RealModePtr] ; get the real mode offset ;*=========================================================================* ; Notify the interrupt that we are updating the mouse ;*=========================================================================* inc [(KeyboardType esi).MouseUpdate] mov ax,[(KeyboardType esi).MCState] cmp al,0 je short ??exit ; if no more nesting clear cond ;*=========================================================================* ;* Decrement the conditional hide counter. ;*=========================================================================* dec al ;*=========================================================================* ;* If there are more conditional levels to undo, then just abort the show. ;*=========================================================================* jne short ??exit ;*=========================================================================* ;* Yup, the mouse should be show, but only if it was previously hidden. ;*=========================================================================* test ax,CONDHIDDEN ; was it hidden by interrupt?? je short ??exit1 ; or initial check for level 0 call Low_Show_Mouse ??exit1: mov ax,0 ??exit: mov [(KeyboardType esi).MCState],ax dec [(KeyboardType esi).MouseUpdate] ret ENDP Conditional_Show_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 VGA_Mouse_Shadow_Buffer:NEAR PROC VGA_Mouse_Shadow_Buffer C NEAR USES eax,ebx,ecx,edx,edi,esi ARG store:DWORD local x0 : dword local y0 : dword local x1 : dword local y1 : dword local buffx0 : dword local buffy0 : dword mov esi,[RealModePtr] ; get 32 bit offset of dos data ;*=========================================================================* ; Direction flag must be forward in this routine. ;*=========================================================================* cld ;*=================================================================== ;* Copy of X, Y, Width and Height into local registers ;*=================================================================== mov eax,[(KeyboardType esi).MouseBuffX] mov ebx,[(KeyboardType esi).MouseBuffY] sub eax,[(KeyboardType esi).MouseXHot] sub ebx,[(KeyboardType esi).MouseYHot] mov [ x0 ] , eax mov [ y0 ] , ebx add eax,[(KeyboardType esi).MouseBuffW] add ebx,[(KeyboardType esi).MouseBuffH] mov [ x1 ] , eax mov [ y1 ] , ebx mov [ buffx0 ] , 0 mov eax , [ MouseBuffer ] mov [ buffy0 ] , eax ;*=================================================================== ;* Bounds check source X. ;*=================================================================== xor eax , eax xor edx , edx mov ecx , [ x0 ] mov ebx , [ x1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ x0 ] mov ebx , [ x1 ] sub ecx , [(KeyboardType esi).MouseRight] sub ebx , [(KeyboardType esi).MouseRight] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] sub ecx , [(KeyboardType esi).MouseBottom] sub ebx , [(KeyboardType esi).MouseBottom] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 xor al , 5 xor dl , 5 mov ah , al test dl , al jnz ??out or al , dl jz ??not_clip test ah , 1000b jz ??scr_left_ok mov ebx , [ x0 ] neg ebx mov [ buffx0 ] , ebx mov [ x0 ] , 0 ??scr_left_ok: test ah , 0010b jz ??scr_bottom_ok mov ebx , [ y0 ] neg ebx imul ebx , [(KeyboardType esi).MouseBuffW] add [ buffy0 ] , ebx mov [ y0 ] , 0 ??scr_bottom_ok: test dl , 0100b jz ??scr_right_ok mov eax , [(KeyboardType esi).MouseRight] ; get width into register mov [ x1 ] , eax ??scr_right_ok: test dl , 0001b jz ??not_clip mov eax , [(KeyboardType esi).MouseBottom] ; get width into register mov [ y1 ] , eax ??not_clip: ;*=================================================================== ;* Get the offset into the screen. ;*=================================================================== mov eax , [ y0 ] mov edx , [(KeyboardType esi).MouseRight] imul eax , edx add eax , [ x0 ] lea edi , [ 0a0000h + eax ] ;*=================================================================== ;* Adjust the source for the top clip. ;*=================================================================== mov ebx , [(KeyboardType esi).MouseBuffW] ; turn this into an offset mov esi , [ buffy0 ] ; edx points to source add esi , [ buffx0 ] ; plus clipped lines ;*=================================================================== ;* Calculate the bytes per row add value ;*=================================================================== mov eax , [ x1 ] mov ecx , [ y1 ] sub eax , [ x0 ] jle ??out sub ecx , [ y0 ] jle ??out sub edx , eax sub ebx , eax push ebp 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 ebp , ecx ??restore_loop: mov ecx,eax ; get number to really write rep movsb ; store them into the buffer add esi,ebx ; move past right clipped pixels add edi,edx ; adjust dest to next line dec ebp ; decrement number of rows to do jnz ??restore_loop ; if more to do, do it pop ebp ret ;*=================================================================== ;* Handle soting the visible page into the Mouse Shadow Buffer ;*=================================================================== ??store_entry: xchg esi,edi ; xchg the source and the dest mov ebp , ecx ??store_loop: mov ecx,eax ; get number to really write rep movsb ; store them into the buffer add esi,edx ; move past right clipped pixels add edi,ebx ; adjust dest to next line dec ebp ; decrement number of rows to do jnz ??store_loop ; if more to do, do it pop ebp ??out: ret ENDP VGA_Mouse_Shadow_Buffer ;*************************************************************************** ;* DRAW_MOUSE -- Handles drawing the mouse cursor * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: Asm callable only! * ;* * ;* HISTORY: * ;* 10/27/1994 PWG : Created. * ;*=========================================================================* GLOBAL VGA_Draw_Mouse:NEAR PROC VGA_Draw_Mouse C NEAR USES eax,ebx,ecx,edx,edi,esi ARG mousex:DWORD ARG mousey:DWORD local x0 : dword local y0 : dword local x1 : dword local y1 : dword local buffx0 : dword local buffy0 : dword mov esi,[RealModePtr] ; get 32 bit offset of dos data ;*=================================================================== ;* Copy of X, Y, Width and Height into local registers ;*=================================================================== mov eax,[mousex] mov ebx,[mousey] sub eax,[(KeyboardType esi).MouseXHot] sub ebx,[(KeyboardType esi).MouseYHot] mov [ x0 ] , eax mov [ y0 ] , ebx add eax,[(KeyboardType esi).MouseWidth] add ebx,[(KeyboardType esi).MouseHeight] mov [ x1 ] , eax mov [ y1 ] , ebx mov [ buffx0 ] , 0 mov eax , [ MouseCursor ] mov [ buffy0 ] , eax ;*=================================================================== ;* Bounds check source X. Y. ;*=================================================================== xor eax , eax xor edx , edx mov ecx , [ x0 ] mov ebx , [ x1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ x0 ] mov ebx , [ x1 ] sub ecx , [(KeyboardType esi).MouseRight] sub ebx , [(KeyboardType esi).MouseRight] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] sub ecx , [(KeyboardType esi).MouseBottom] sub ebx , [(KeyboardType esi).MouseBottom] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 xor al , 5 xor dl , 5 mov ah , al test dl , al jnz ??out or al , dl jz ??not_clip test ah , 1000b jz ??scr_left_ok mov ebx , [ x0 ] neg ebx mov [ buffx0 ] , ebx mov [ x0 ] , 0 ??scr_left_ok: test ah , 0010b jz ??scr_bottom_ok mov ebx , [ y0 ] neg ebx imul ebx , [(KeyboardType esi).MouseWidth] add [ buffy0 ] , ebx mov [ y0 ] , 0 ??scr_bottom_ok: test dl , 0100b jz ??scr_right_ok mov eax , [(KeyboardType esi).MouseRight] ; get width into register mov [ x1 ] , eax ??scr_right_ok: test dl , 0001b jz ??not_clip mov eax , [(KeyboardType esi).MouseBottom] ; get width into register mov [ y1 ] , eax ??not_clip: ;*=================================================================== ;* Get the offset into the screen. ;*=================================================================== mov eax , [ y0 ] mov edx , [(KeyboardType esi).MouseRight] imul eax , edx add eax , [ x0 ] lea edi , [ 0a0000h + eax ] ;*=================================================================== ;* Adjust the source for the top clip. ;*=================================================================== mov ebx , [(KeyboardType esi).MouseWidth] ; turn this into an offset mov esi , [ buffy0 ] ; edx points to source add esi , [ buffx0 ] ; plus clipped lines ;*=================================================================== ;* Calculate the bytes per row add value ;*=================================================================== mov eax , [ x1 ] mov ecx , [ y1 ] sub eax , [ x0 ] jle ??out sub ecx , [ y0 ] jle ??out sub edx , eax sub ebx , eax ;*=================================================================== ;* Handle restoring the buffer to the visible page ;*=================================================================== ??top_loop: mov ah,al ??inner_loop: mov ch ,[esi] inc esi or ch,ch jz ??inc_edi mov [edi],ch ??inc_edi: inc edi dec ah jnz ??inner_loop add esi,ebx ; move past right clipped pixels add edi,edx ; adjust dest to next line dec cl ; decrement number of rows to do jnz ??top_loop ; if more to do, do it ??out: 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:NEAR PROC VESA_Mouse_Shadow_Buffer C NEAR USES eax,ebx,ecx,edx,edi,esi ARG store:DWORD local x0 : dword local y0 : dword local x1 : dword local y1 : dword local buffx0 : dword local buffy0 : dword local vesa_linear : dword mov eax , [ cpu_video_page ] mov [ vesa_linear ] , eax mov esi,[RealModePtr] ; get 32 bit offset of dos data ;*=========================================================================* ; Direction flag must be forward in this routine. ;*=========================================================================* ;*=================================================================== ;* Copy of X, Y, Width and Height into local registers ;*=================================================================== mov eax,[(KeyboardType esi).MouseBuffX] mov ebx,[(KeyboardType esi).MouseBuffY] sub eax,[(KeyboardType esi).MouseXHot] sub ebx,[(KeyboardType esi).MouseYHot] mov [ x0 ] , eax mov [ y0 ] , ebx add eax,[(KeyboardType esi).MouseBuffW] add ebx,[(KeyboardType esi).MouseBuffH] mov [ x1 ] , eax mov [ y1 ] , ebx mov [ buffx0 ] , 0 mov eax , [ MouseBuffer ] mov [ buffy0 ] , eax ;*=================================================================== ;* Bounds check source X. ;*=================================================================== xor eax , eax xor edx , edx mov ecx , [ x0 ] mov ebx , [ x1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ x0 ] mov ebx , [ x1 ] sub ecx , [(KeyboardType esi).MouseRight] sub ebx , [(KeyboardType esi).MouseRight] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] sub ecx , [(KeyboardType esi).MouseBottom] sub ebx , [(KeyboardType esi).MouseBottom] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 xor al , 5 xor dl , 5 mov ah , al test dl , al jnz ??out or al , dl jz ??not_clip test ah , 1000b jz ??scr_left_ok mov ebx , [ x0 ] neg ebx mov [ buffx0 ] , ebx mov [ x0 ] , 0 ??scr_left_ok: test ah , 0010b jz ??scr_bottom_ok mov ebx , [ y0 ] neg ebx imul ebx , [(KeyboardType esi).MouseBuffW] add [ buffy0 ] , ebx mov [ y0 ] , 0 ??scr_bottom_ok: test dl , 0100b jz ??scr_right_ok mov eax , [(KeyboardType esi).MouseRight] ; get width into register mov [ x1 ] , eax ??scr_right_ok: test dl , 0001b jz ??not_clip mov eax , [(KeyboardType esi).MouseBottom] ; get width into register mov [ y1 ] , eax ??not_clip: ;*=================================================================== ;* Get the offset into the screen. ;*=================================================================== mov eax , [ y0 ] mov edx , [(KeyboardType esi).MouseRight] imul eax , edx add eax , [ x0 ] lea edi , [ 0a0000h + eax ] call Vesa_Asm_Set_Win ;*=================================================================== ;* Adjust the source for the top clip. ;*=================================================================== mov ebx , [(KeyboardType esi).MouseBuffW] ; turn this into an offset mov esi , [ buffy0 ] ; edx points to source add esi , [ buffx0 ] ; plus clipped lines ;*=================================================================== ;* Calculate the bytes per row add value ;*=================================================================== mov eax , [ x1 ] mov ecx , [ y1 ] sub eax , [ x0 ] jle ??out sub ecx , [ y0 ] jle ??out sub edx , eax sub ebx , eax 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 [ tempreg ] , ebx ??restore__top_loop: mov ah,al ??restore__inner_loop: mov ch ,[esi] mov [edi],ch inc esi inc edi mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??restore__in_range add edi , [ cpu_video_page ] call Vesa_Asm_Set_Win ??restore__in_range: dec ah jnz ??restore__inner_loop add esi,[ tempreg ] ; move past right clipped pixels add edi,edx ; adjust dest to next line mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??restore__in_range1 add edi ,[ cpu_video_page ] call Vesa_Asm_Set_Win ??restore__in_range1: dec cl ; decrement number of rows to do jnz ??restore__top_loop ; if more to do, do it jmp ??out ; get the heck outta the routine ;*=================================================================== ;* Handle soting the visible page into the Mouse Shadow Buffer ;*=================================================================== ??store_entry: mov [ tempreg ] , ebx ??store_top_loop: mov ah,al ??store_inner_loop: mov ch ,[edi] mov [esi],ch inc esi inc edi mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??store_in_range add edi ,[ cpu_video_page ] call Vesa_Asm_Set_Win ??store_in_range: dec ah jnz ??store_inner_loop add esi,[ tempreg ] ; move past right clipped pixels add edi,edx ; adjust dest to next line mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??store_in_range1 add edi ,[ cpu_video_page ] call Vesa_Asm_Set_Win ??store_in_range1: dec cl ; decrement number of rows to do jnz ??store_top_loop ; if more to do, do it ??out: mov edi , [ vesa_linear ] add edi , 0a0000h call Vesa_Asm_Set_Win ret ENDP VESA_Mouse_Shadow_Buffer ;*************************************************************************** ;* DRAW_MOUSE -- Handles drawing the mouse cursor * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: Asm callable only! * ;* * ;* HISTORY: * ;* 10/27/1994 PWG : Created. * ;*=========================================================================* GLOBAL VESA_Draw_Mouse:NEAR PROC VESA_Draw_Mouse C NEAR USES eax,ebx,ecx,edx,edi,esi ARG mousex:DWORD ARG mousey:DWORD local x0 : dword local y0 : dword local x1 : dword local y1 : dword local buffx0 : dword local buffy0 : dword local tempreg : dword local vesa_linear : dword mov eax , [ cpu_video_page ] mov [ vesa_linear ] , eax mov esi,[RealModePtr] ; get 32 bit offset of dos data ;*=================================================================== ;* Copy of X, Y, Width and Height into local registers ;*=================================================================== mov eax,[mousex] mov ebx,[mousey] sub eax,[(KeyboardType esi).MouseXHot] sub ebx,[(KeyboardType esi).MouseYHot] mov [ x0 ] , eax mov [ y0 ] , ebx add eax,[(KeyboardType esi).MouseWidth] add ebx,[(KeyboardType esi).MouseHeight] mov [ x1 ] , eax mov [ y1 ] , ebx mov [ buffx0 ] , 0 mov eax , [ MouseCursor ] mov [ buffy0 ] , eax ;*=================================================================== ;* Bounds check source X. Y. ;*=================================================================== xor eax , eax xor edx , edx mov ecx , [ x0 ] mov ebx , [ x1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ x0 ] mov ebx , [ x1 ] sub ecx , [(KeyboardType esi).MouseRight] sub ebx , [(KeyboardType esi).MouseRight] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] shld eax , ecx , 1 shld edx , ebx , 1 mov ecx , [ y0 ] mov ebx , [ y1 ] sub ecx , [(KeyboardType esi).MouseBottom] sub ebx , [(KeyboardType esi).MouseBottom] dec ecx dec ebx shld eax , ecx , 1 shld edx , ebx , 1 xor al , 5 xor dl , 5 mov ah , al test dl , al jnz ??out or al , dl jz ??not_clip test ah , 1000b jz ??scr_left_ok mov ebx , [ x0 ] neg ebx mov [ buffx0 ] , ebx mov [ x0 ] , 0 ??scr_left_ok: test ah , 0010b jz ??scr_bottom_ok mov ebx , [ y0 ] neg ebx imul ebx , [(KeyboardType esi).MouseWidth] add [ buffy0 ] , ebx mov [ y0 ] , 0 ??scr_bottom_ok: test dl , 0100b jz ??scr_right_ok mov eax , [(KeyboardType esi).MouseRight] ; get width into register mov [ x1 ] , eax ??scr_right_ok: test dl , 0001b jz ??not_clip mov eax , [(KeyboardType esi).MouseBottom] ; get width into register mov [ y1 ] , eax ??not_clip: ;*=================================================================== ;* Get the offset into the screen. ;*=================================================================== mov eax , [ y0 ] mov edx , [(KeyboardType esi).MouseRight] imul eax , edx add eax , [ x0 ] lea edi , [ 0a0000h + eax ] call Vesa_Asm_Set_Win ;*=================================================================== ;* Adjust the source for the top clip. ;*=================================================================== mov ebx , [(KeyboardType esi).MouseWidth] ; turn this into an offset mov esi , [ buffy0 ] ; edx points to source add esi , [ buffx0 ] ; plus clipped lines ;*=================================================================== ;* Calculate the bytes per row add value ;*=================================================================== mov eax , [ x1 ] mov ecx , [ y1 ] sub eax , [ x0 ] jle ??out sub ecx , [ y0 ] jle ??out sub edx , eax sub ebx , eax ;*=================================================================== ;* Handle restoring the buffer to the visible page ;*=================================================================== mov [ tempreg ] , ebx ??top_loop: mov ah,al ??inner_loop: mov ch ,[esi] inc esi or ch,ch jz ??inc_edi mov [edi],ch ??inc_edi: inc edi mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??in_range add edi ,[ cpu_video_page ] call Vesa_Asm_Set_Win ??in_range: dec ah jnz ??inner_loop add esi,[ tempreg ] ; move past right clipped pixels add edi,edx ; adjust dest to next line mov ebx , edi add ebx , [ cpu_video_page ] cmp ebx , [ cpu_page_limit ] jl ??in_range1 add edi ,[ cpu_video_page ] call Vesa_Asm_Set_Win ??in_range1: dec cl ; decrement number of rows to do jnz ??top_loop ; if more to do, do it ??out: mov edi , [ vesa_linear ] add edi , 0a0000h call Vesa_Asm_Set_Win ret ENDP VESA_Draw_Mouse ;---------------------------------------------------------------------------- END