;�������������������������������������������������������������������������Ŀ
;�       NICE & FAST MOUSE for mode 12h (640 x 480 in 16 colours)          ��
;�               routines in Turbo Assembler for a real mode               ��
;�                      by Holy Drake / The Guardians                      ��
;�                               version 1.01                              ��
;�  original idea of setting a new mouse handler is taken from XLIB.MOUSE  ��
;�          Turbo Pascal unit by Themie Gouthas & Christian Harms          ��
;��������������������������������������������������������������������������ٱ
; ���������������������������������������������������������������������������



.286
.Model Tiny
DOSSEG
.Stack 500h


Mouse12H_Code SEGMENT

ASSUME CS:Mouse12H_Code,DS:Mouse12H_Code,ES:Mouse12H_Code



                True = 255          ;Define nice constants
               False = 0
         ScreenSizeX EQU 640
         ScreenSizeY EQU 480
  ScreenWidthInBytes EQU 80
BackGroundTempOffset EQU 65535-2000 ;Address in a graphic memory of a buffer
                                    ;for the background behind the cursor


; Variables
           VisAddr DW 0        ; <- offset of the upper-left corner
    MouseInstalled DB False    ; <- TRUE if mouse handler installed
                               ;    (procedure MyMouseInit)
       MouseHidden DB True     ; <- TRUE if mouse handler installed
                               ;    but mouse cursor is hidden (HideMouse)
           MHidden DB False    ; <- TRUE if mouse hidden by procedure
                               ;    called HideUntilMoved
      ButtonStatus DW 0        ; <- actual status of all mouse buttons
                               ;    &01-LeftButton,&02-RightButton,&04-Middle
            MouseX DW 1        ; <- coordinates of the mouse cursor
            MouseY DW 0        ; <- (when cursor is hidden also)
         InHandler DB False    ; <- TRUE if handler procedure execute
              OldX DW 0        ; <- last coordinates
              OldY DW 0

; 0FFh or 255 in a cursor shape table means a colour of background
; (made of glass)

CursorShape DD ? ; <- pointer to the cursor shape table
     PointX DW 0 ; <- tells where the middle of the cursor is
     PointY DW 0 ; </


; This cursor shape table is a bitmap 16 by 24 pixels (made of sixteen
; vertical and 24-pixel lines)
; First two words are moved to PointX and PointY

kursor1  DW 0,0
         DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
         DB 000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh
         DB 00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh
         DB 00Eh,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh
         DB 00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh
         DB 00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh
         DB 00Eh,00Eh,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h
         DB 00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,000h,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh
         DB 00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,000h,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,00Eh,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,00Eh,000h
         DB 000h,00Eh,00Eh,00Eh,00Eh,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,000h,00Eh,00Eh,00Eh,000h,0FFh,000h,000h,00Eh,00Eh,00Eh,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,00Eh,000h
         DB 0FFh,0FFh,0FFh,000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Eh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh


 Kursor2 DW 6,9
         DB 000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,000h,00Ah,000h,000h,000h,000h,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,00Ah,000h,00Fh,00Fh,007h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,00Fh,00Fh
         DB 008h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh,000h,00Ah,000h,00Fh,00Fh,00Fh,007h,000h
         DB 0FFh,0FFh,0FFh,000h,00Fh,00Fh,00Fh,007h,000h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,00Ah,000h,00Fh,00Fh,00Fh,000h,007h,000h,0FFh,000h,00Fh,00Fh,00Fh,007h,000h
         DB 008h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh,000h,00Ah,000h,00Fh,00Fh,007h,00Fh,000h
         DB 007h,000h,00Fh,00Fh,00Fh,007h,000h,007h,000h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,00Ah,000h,00Fh,00Fh,00Fh,000h,007h,000h,00Fh,007h,00Fh,00Fh,000h,007h,000h
         DB 008h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh,000h,00Ah,000h,00Fh,00Fh,007h,007h,000h
         DB 007h,000h,00Fh,00Fh,00Fh,007h,000h,007h,000h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,00Ah,000h,00Fh,00Fh,00Fh,000h,007h,000h,0FFh,000h,00Fh,00Fh,00Fh,008h,000h
         DB 008h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh,000h,00Ah,000h,00Fh,00Fh,00Fh,007h,000h
         DB 0FFh,0FFh,0FFh,000h,00Fh,00Fh,007h,008h,000h,000h,00Ah,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,00Eh,000h,00Fh,00Fh,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,00Fh,008h
         DB 008h,000h,00Eh,000h,0FFh,0FFh,0FFh,0FFh,000h,00Eh,000h,000h,000h,000h,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,00Eh,000h,0FFh,0FFh,0FFh,0FFh
         DB 000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh

 Kursor3 DW 7,7
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,00Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,000h,000h,000h,000h,000h,000h,00Fh,000h,000h,000h,000h,000h,000h,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,0FFh
         DB 00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,000h,000h,000h,000h,000h,000h,00Fh,000h,000h,000h,000h,000h,000h,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh
         DB 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,00Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh

 Kursor4 DW 7,8
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,00Fh,00Fh
         DB 00Fh,00Fh,00Fh,00Fh,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,000h,00Fh,00Fh,00Fh,00Fh,000h,000h,00Fh,00Fh,00Fh,00Fh,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,0FFh,0FFh,000h,00Fh,00Fh,000h,00Fh
         DB 00Fh,00Fh,00Fh,000h,007h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 000h,0FFh,000h,00Fh,00Fh,00Fh,008h,00Fh,00Fh,00Fh,00Fh,000h,000h,00Fh,00Fh,000h
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,008h,000h,000h,00Fh,000h,000h,007h,00Fh
         DB 00Fh,00Fh,00Fh,007h,000h,00Fh,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,000h,00Fh,00Fh,007h,000h,000h,007h,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,000h
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,000h,00Fh,00Fh,007h
         DB 000h,000h,00Fh,00Fh,00Fh,000h,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,000h,00Fh,000h,00Fh,00Fh,007h,000h,000h,00Fh,00Fh,00Fh,000h,00Fh,000h
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,00Fh,00Fh,007h,000h
         DB 007h,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 008h,000h,000h,00Fh,00Fh,007h,000h,007h,00Fh,00Fh,00Fh,007h,000h,00Fh,00Fh,000h
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,0FFh,000h,00Fh,00Fh,000h,007h,00Fh
         DB 00Fh,00Fh,00Fh,000h,000h,00Fh,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 000h,0FFh,0FFh,000h,00Fh,00Fh,007h,00Fh,00Fh,00Fh,00Fh,000h,007h,00Fh,000h,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,00Fh,00Fh,00Fh,00Fh
         DB 000h,000h,00Fh,00Fh,00Fh,00Fh,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,000h,000h,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,000h,000h,0FFh,0FFh
         DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h
         DB 000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh




;����������������������������������������������������������������������
RestoreBG PROC NEAR
; DON'T CALL IT
; AX = Y,   BX = X
         sub ax,[cs:PointY]
         sub bx,[cs:PointX]
         push ds
         push ax
         mov dx,03CEh
         mov ax,8
         out dx,ax
         mov dx,03C4h
         mov al,2
         out dx,al
         inc dx
         mov al,0Fh
         out dx,al
         pop ax
         mov cx,ScreenWidthInBytes
         mul cx
         sar bx,3
         add ax,bx
         mov si,BackGroundTempOffset
         mov di,ax
         add di,[cs:VisAddr]
         mov ax,0A000h
         mov es,ax
         mov ds,ax
         mov cx,24
         cld
p1:      movsb
         movsb
         movsb
         add di,ScreenWidthInBytes-3
         loop p1
         mov dx,03CFh
         mov al,0FFh
         out dx,al
         pop ds
         retn
RestoreBG ENDP
;����������������������������������������������������������������������
GetBG PROC NEAR
; DON'T CALL IT
; AX = Y,   BX = X
         sub ax,[cs:PointY]
         sub bx,[cs:PointX]
         push ds
         push ax
         mov dx,3CEh
         mov ax,8
         out dx,ax
         mov dx,3C4h
         mov al,2
         out dx,al
         inc dx
         mov al,0Fh
         out dx,al
         pop ax
         mov cx,ScreenWidthInBytes
         mul cx
         sar bx,3
         add ax,bx
         mov di,BackGroundTempOffset
         mov si,ax
         add si,[cs:VisAddr]
         mov ax,0A000h
         mov es,ax
         mov ds,ax
         mov cx,24
         cld
p2:      movsb
         movsb
         movsb
         add si,ScreenWidthInBytes-3
         loop p2
         mov dx,03CFh
         mov al,0FFh
         out dx,al
         pop ds
         retn
GetBG ENDP
;����������������������������������������������������������������������
EnX DW ?
PutCursor PROC NEAR
; DON'T CALL IT
; CX-y; BX-x;
         cld
         sub cx,[cs:PointY]
         sub bx,[cs:PointX]
         mov [cs:enX],bx
         mov ax,ScreenWidthInBytes
         mul cx
         mov di,ax
         mov cx,bx
         sar bx,3
         add di,[cs:VisAddr]
         add di,bx
         mov bx,cx
         and bx,7
         mov ax,0A000h
         mov es,ax
         push ds
         lds si,[cs:dword ptr CursorShape]
         mov dx,03CEh
         mov ax,0205h
         out dx,ax
         mov ax,3
         out dx,ax
         mov cx,16
petlaX:  push cx
         cmp [cs:enX],0
         jge dupa
         add si,24 ;Jump over one vertical line of bitmap
         jmp uff0  ;Don't draw this line
dupa:    mov cl,bl
         and cl,7
         mov ah,128
         shr ah,cl
         mov al,8
         out dx,ax
         mov cx,24
         push di
petlaY:  lodsb
         cmp al,255
         jz DONTPUT
         mov ah,[es:di]
         mov [es:di],al
DONTPUT: add di,ScreenWidthInBytes
         loop petlaY
         pop di
uff0:    inc bx
         mov al,bl
         and al,7
         cmp al,0
         jnz uff
         inc di
uff:     inc [cs:enX]
         pop cx
         cmp [cs:enX],ScreenSizeX
         jge dosc1
LeavLin: loop petlaX
dosc1:
         mov ax,0FF08h
         out dx,ax
         mov ax,5
         out dx,ax
         mov ax,3
         out dx,ax
         pop ds
         retn
PutCursor ENDP
;����������������������������������������������������������������������
HideMouse PROC FAR
; Makes mouse cursor invisible
         push ds
         push cs
         pop ds
         cmp [MouseInstalled],FALSE
         je  NoAction0
         cmp [MouseHidden],FALSE
         jne NoAction0
WaitEndOfHandler0:
         mov cl,[InHandler]
         or cl,cl
         jnz WaitEndOfHandler0
         mov [MouseHidden],TRUE
         cmp [MHidden],TRUE
         jz NoAction0
         mov ax,[OldY]
         mov bx,[OldX]
         call restoreBG
NoAction0:
         pop ds
         retf
HideMouse ENDP
;����������������������������������������������������������������������
ShowMouse PROC FAR
; Makes him visible
         push ds
         push cs
         pop ds
         cmp [MouseInstalled],FALSE
         je  NoAction1
         cmp [MouseHidden],FALSE
         je  NoAction1
WaitEndOfHandler2:
         mov cl,[InHandler]
         or cl,cl
         jnz WaitEndOfHandler2
         mov ax,[MouseY]
         mov bx,[MouseX]
         mov [OldY],ax
         mov [OldX],bx
         call getBG
         cmp [MHidden],TRUE
         jz NoACtion1
         mov bx,[OldX]
         mov cx,[OldY]
         call PutCursor
NoAction1:
         mov [MouseHidden],FALSE
         pop ds
         retf
ShowMouse ENDP
;����������������������������������������������������������������������
SetMouseSpeed PROC FAR
; Set the speed of the mouse cursor
; Put horizontal (X) speed in CX and vertical (Y) speed in DX
         cmp [cs:MouseInstalled],FALSE
         jz SDalej
         mov ax,0Fh
         int 33h
SDalej:  retf
SetMouseSpeed ENDP
;����������������������������������������������������������������������
Maus_Handler PROC FAR
; DON'T CALL IT
; It's an interrupt handler for a mouse cursor !!!
         pushf
         cmp [cs:InHandler],TRUE
         je  NoAction3
         push es
         push ds
         push si
         push di
         push ax
         push bx
         push cx
         push dx
         push cs
         pop ds
         mov [InHandler],TRUE
         and bx,3
         mov [ButtonStatus],bx
         mov [MouseX],cx
         mov [MouseY],dx
         cmp [MouseHidden],TRUE
         jz NoAction2
         cmp [MHidden],TRUE
         jz UnHide
; WaitVSyncStart
         mov  dx,3DAh
 a1:     in   al,dx
         test al,8
         jnz  a1
 a2:     in   al,dx
         test al,8
         jz a2

         mov ax,[OldY]
         mov bx,[OldX]
         call restoreBG
BBB1:    mov ax,[MouseY]
         mov bx,[MouseX]
         mov [OldY],ax
         mov [OldX],bx
         call getBG
         mov bx,[MouseX]
         mov cx,[MouseY]
         call PutCursor
         jmp NoACtion2
UnHide:  mov [MHidden],FALSE
         jmp BBB1
NoAction2:
         mov [InHandler],FALSE
         pop dx
         pop cx
         pop bx
         pop ax
         pop di
         pop si
         pop ds
         pop es
NoAction3:
         popf
         retf
Maus_Handler ENDP
;����������������������������������������������������������������������
MyMouseInit PROC FAR
; Initialization of the handler !
; That's a first procedure you should execute !
         push ds
         push cs
         pop ds
         cmp [MouseInstalled],TRUE
         je  EndNo

         xor ax,ax
         int 33h
         or  ax,ax
         jz  EndNo

;  mov ButtonCount,bl

         mov ax,02
         int 33h

         mov ax,07h
         mov cx,0
         mov dx,ScreenSizeX-1
         int 33h

         mov ax,08h
         mov cx,0
         mov dx,ScreenSizeY-1
         int 33h

         mov ax,12
         mov bx,cs
         mov es,bx
         mov dx,OFFSET Maus_Handler
         mov cx,1Fh
         int 33h

         mov [MouseInstalled],TRUE
         mov [MouseHidden],TRUE
         mov ax,320
         mov [MouseX],ax
         mov ax,240
         mov [MouseY],ax
         mov [ButtonStatus],0
EndNo:   pop ds
         retf
MyMouseInit ENDP
;����������������������������������������������������������������������
SetMouseWindow PROC FAR Y2:WORD,X2:WORD,Y1:WORD,X1:WORD
; Set the size of the mouse window
; Put parameters on the stack
         push bp
         mov bp,sp
         cmp [cs:MouseInstalled],FALSE
         jz SMDalej
         mov ax,07h            ; Set Min/Max horiz. position
         mov cx,x1
         mov dx,x2
         int 33h

         mov ax,08h            ; Set Min/Max vertical position
         mov cx,y1
         mov dx,y2
         int 33h
SMDalej: pop bp
         retf 0008h
SetMouseWindow ENDP
;����������������������������������������������������������������������
MyMouseDestroy PROC FAR
; Restore old mouse handler - kill new mouse handler
         push ds
         push cs
         pop ds
         cmp [MouseInstalled],FALSE
         je  EndNo2

         call HideMouse
         mov ax,12
         xor cx,cx
         int 33h
         mov MouseInstalled,false
EndNo2:  pop ds
         retf
MyMouseDestroy ENDP
;����������������������������������������������������������������������
SetMousePos PROC FAR
; Set the cursor position on the screen
; Put X position in CX and Y position in DX
         cmp [cs:MouseInstalled],FALSE
         jz SMPDalj

         mov [cs:MouseX],cx
         mov [cs:MouseY],dx
         mov ax,4
         int 33h
SMPDalj: retf
SetMousePos ENDP
;����������������������������������������������������������������������
HideUntilMoved PROC FAR
; Hide the mouse cursor till somebody move a mouse
         cmp [cs:MouseInstalled],FALSE
         jz H2Dalej
         cmp [cs:MHidden],TRUE
         jz H2Dalej
         mov ax,[cs:OldY]
         mov bx,[cs:OldX]
         call restoreBG
         mov [cs:MHidden],TRUE
         mov cx,[cs:MouseX]
         or cx,cx
         jnz H2_D1
         mov cx,1
H2_D1:   cmp cx,ScreenSizeX
         jnz H2_D2
         mov cx,ScreenSizeX-1
H2_D2:   mov dx,[cs:MouseY]
         call SetMousePos
H2Dalej: retf
HideUntilMoved ENDP
;����������������������������������������������������������������������
DefineCursor PROC FAR
; Set an address where the shape of the cursor is stored
; Remember to hide a cursor first
         mov ax,[es:di]
         mov [cs:PointX],ax
         mov ax,[es:di][2]
         mov [cs:PointY],ax
         add di,4
         mov [word ptr cs:CursorShape],di
         mov [word ptr cs:CursorShape+2],es
         retf
DefineCursor ENDP
;����������������������������������������������������������������������
IsThereAnyMouse PROC FAR
; Returns 0FFh in AL if mouse driver installed
         xor ax,ax
         int 33h
         and al,ah
         retf
IsThereAnyMouse ENDP
;�����������������������������������������������������������������������������


;           �������������������������������������
;           �������������������������������������
;           �� HERE A DEMO PROGRAM CODE STARTS ��
;           �������������������������������������
;           �������������������������������������

Text1 DB 'X=        Y=         Buttons=',13,10
      DB '�������������������������������������������������������������������������Ŀ',13,10
      DB '�       NICE & FAST MOUSE for mode 12h (640 x 480 in 16 colours)          ��',13,10
      DB '�               routines in Turbo Assembler for a real mode               ��',13,10
      DB '�                      by Holy Drake / The Guardians                      ��',13,10
      DB '�                               version 1.01                              ��',13,10
      DB '��������������������������������������������������������������������������ٱ',13,10
      DB ' ���������������������������������������������������������������������������',13,10
      DB 13,10,13,10
      DB 'Press 1, 2, 3 or 4 to change a mouse cursor shape !',13,10
      DB 'Press mouse button to get mouse coordinates.',13,10
      DB 'You can even press ESC to leave this wonderful show !$'
TBUFF DB 10 DUP ('0')
  Bye DB 'Mouse not installed! Go and buy it now!',13,10,'$'

ShowDXasDEC PROC NEAR
; Display a DX register as a decimal value
         push   ds   ;Save registers
         push   di
         push   dx
         push   cx
         push   ax
         push   cs
         pop    ds
;Put the digits in a buffer
         xor    cx,cx     ;Initialize the counter
         lea    di,TBUFF  ;Point to the buffer
DEC16OUT1:
         push   cx                     ;Save CX
         mov    ax,dx                  ;Numerator
         xor    dx,dx                  ;Clear upper half
         mov    cx,10                  ;Divisor of 10
         div    cx                     ;Divide
         xchg   ax,dx                  ;Get quotient
         add    al,30h                 ;Add 30H
         mov    [di],al                ;Put in buffer
         inc    di                     ;Next byte
         pop    cx                     ;Restore CX
         inc    cx                     ;Count the digit
         or     dx,dx                  ;Done?
         jnz    DEC16OUT1
;Dump the buffer out
DEC16OUT2:
         dec    di                     ;Back up through the buffer
         mov    dl,[DI]                ;Get byte from buffer
         mov    ah,2
         int    21h  ;<- Write it to the screen
         loop   DEC16OUT2
         mov    cx,4
ClearIt: mov    ah,2
         mov    dl,' '
         push   cx
         int    21h
         pop    cx
         loop   ClearIt
         pop    ax                     ;Restore registers
         pop    cx
         pop    dx
         pop    di
         pop    ds
         ret                           ;Return
ShowDXasDEC ENDP

ShowCoordinates PROC NEAR
         call HideMouse
         mov dl,2
         mov dh,0
         mov bh,0
         mov ah,2
         int 10h
         mov dx,[cs:MouseX] ;A binary number is in DX
         call ShowDXasDEC

         mov dl,12
         mov dh,0
         mov bh,0
         mov ah,2
         int 10h
         mov dx,[cs:MouseY]
         call ShowDXasDEC

         mov dl,29
         mov dh,0
         mov bh,0
         mov ah,2
         int 10h
         mov dx,[cs:ButtonStatus]
         call ShowDXasDEC
         call ShowMouse
Pusc:    cmp [ButtonStatus],0
         jne Pusc
         retn
ShowCoordinates ENDP

Start:   call IsThereAnyMouse
         cmp al,0FFh
         jz Ok_MouseFound
         push cs
         pop ds
         mov dx,OFFSET Bye
         mov ah,9
         int 21h
         mov ah,4Ch
         int 21h
Ok_MouseFound:


         mov ax,12h           ;Initialize my best graphic mode
         int 10h

         mov ax,Mouse12H_Code  ;Write some sribblings
         mov ds,ax
         mov dx,OFFSET Text1
         mov ah,9
         int 21h

         push cs
         pop es
         mov di,OFFSET Kursor1
         call DefineCursor

         call MyMouseInit      ;Install new mouse handler

         mov cx,6
         mov dx,6
         call SetMouseSpeed

         push 0
         push 30
         push 639
         push 479
         call SetMouseWindow



         call ShowMouse        ;Enable cursor

REPEAT:  ; Thiz is main loop
         cmp [ButtonStatus],0
         je DontShow
         call ShowCoordinates
DontShow:
         mov ah,01
         int 16h
         jz NieMa
         xor ah,ah
         int 16h ;<- Get a key code to AL
         cmp al,27
         jz Finito
         cmp al,'1'
         jnz No1
         call HideMouse
         push cs
         pop es
         mov di,OFFSET Kursor1
         call DefineCursor
         call ShowMouse
         jmp Repeat
No1:     cmp al,'2'
         jnz No2
         call HideMouse
         push cs
         pop es
         mov di,OFFSET Kursor2
         call DefineCursor
         call ShowMouse
         jmp Repeat
No2:     cmp al,'3'
         jnz No3
         call HideMouse
         push cs
         pop es
         mov di,OFFSET Kursor3
         call DefineCursor
         call ShowMouse
         jmp Repeat
No3:     cmp al,'4'
         jnz No4
         call HideMouse
         push cs
         pop es
         mov di,OFFSET Kursor4
         call DefineCursor
         call ShowMouse
No4:
NieMa:   jmp REPEAT


Finito:  call HideMouse        ;Disable cursor
         call MyMouseDestroy   ;Restore old mouse handler

         mov ax,3
         int 10h
         mov ah,4Ch  ;See you in DOS!
         int 21h
Mouse12H_Code ENDS
END Start