;MOUSEKEY.COM for the Microsoft Mouse - 1987 by Jeff Prosise
;
bios_data     segment at 40h
              org 1Ah
buffer_head   dw ?                          ;pointer to keyboard buffer head
buffer_tail   dw ?                          ;pointer to keyboard buffer tail
              org 80h
buffer_start  dw ?                          ;starting keyboard buffer address
buffer_end    dw ?                          ;ending keyboard buffer address
bios_data     ends
;
code          segment para public 'code'
              assume cs:code
              org 100h
begin:        jmp initialize                ;goto initialization code
;
copyright          db 'Copyright 1987 Ziff-Davis Publishing Co.'
author             db 'Written by Jeff Prosise'
vcount             db 3                     ;vertical delay counter
hflag              dw ?                     ;horizontal count sign flag
vflag              dw ?                     ;vertical count sign flag
keycode            db 4Dh,4Bh,50h,48h       ;keycodes for cursor keys
;
;------------------------------------------------------------------------------
;MOUSE subroutine is handed control by the mouse driver when either the mouse
;is moved or either button is pressed.
;------------------------------------------------------------------------------
mouse         proc far
;
;Determine which event occurred and branch accordingly.
;
              test ax,2                     ;was the left button pressed?
              jnz pgup                      ;yes, then branch
              test ax,8                     ;was the right button pressed?
              jnz pgdn                      ;yes, then branch
;
;Move the cursor in the direction indicated by the most recent mouse move.
;
mouse0:       mov ax,11                     ;function 11
              int 51                        ;read mouse motion counters
              mov hflag,0                   ;initialize sign flags
              mov vflag,2
              xor al,al                     ;zero AL for extended keycode
              cmp cx,0                      ;horizontal count positive?
              jge mouse1                    ;yes, then branch
              inc hflag                     ;record negative condition
              neg cx                        ;convert negative to positive
mouse1:       cmp dx,0                      ;vertical count positive?
              jge mouse2                    ;yes, then branch
              inc vflag                     ;record negative condition
              neg dx                        ;convert negative to positive
mouse2:       mov bx,hflag                  ;assume motion was horizontal
              cmp cx,dx                     ;was the assumption correct?
              jae mouse3                    ;yes, then branch
              mov bx,vflag                  ;no, then correct it
              dec vcount                    ;decrement vertical delay count
              jz mouse3                     ;continue if count is zero
              ret                           ;exit if it's not
mouse3:       mov vcount,3                  ;reset delay counter
              mov ah,keycode[bx]            ;get keycode from table
              jmp insert                    ;insert it into keyboard buffer
;
;The left button was pressed.  Load AX with the keycode for the PgUp key.
;
pgup:         mov ax,4900h                  ;load keycode
              jmp insert                    ;insert it into the keyboard buffer
;
;The right button was pressed.  Load AX with the keycode for PgDn.
;
pgdn:         mov ax,5100h                  ;load keycode
;
;Insert the keycode in AX into the keyboard buffer.
;
insert:       mov bx,bios_data              ;point DS to BIOS data area
              mov ds,bx
              assume ds:bios_data
              cli                           ;disable interrupts
              mov bx,buffer_tail            ;get buffer tail address
              mov dx,bx                     ;transfer it to DX
              add dx,2                      ;calculate next buffer position
              cmp dx,buffer_end             ;did we overshoot the end?
              jne insert1                   ;no, then continue
              mov dx,buffer_start           ;yes, then wrap around
insert1:      cmp dx,buffer_head            ;is the buffer full?
              je insert2                    ;yes, then end now
              mov [bx],ax                   ;insert the keycode
              mov bx,dx                     ;advance the tail
              mov buffer_tail,bx            ;record its new position
insert2:      sti                           ;enable interrupts
              assume ds:nothing
              ret                           ;exit user-defined subroutine
mouse         endp
;
;------------------------------------------------------------------------------
;INITIALIZE routine points the mouse driver to the user-defined subroutine,
;then leaves it resident in memory.
;------------------------------------------------------------------------------
initialize    proc near
              jmp init0                     ;skip transient data area
;
errmsg        db 13,10,'Mouse Not Installed',13,10,'$'
;
;Make sure the mouse hardware and software are in place.
;
init0:        mov ax,0                      ;function 0
              int 51                        ;get installation flag
              or ax,ax                      ;is AX zero?
              jne init1                     ;no, then installation OK
              mov ah,9                      ;print error message and abort
              lea dx,errmsg
              int 21h
              ret
;
;Point the mouse driver to the user-defined subroutine that will be executed
;anytime the mouse is moved or a button is pressed.
;
init1:        mov ax,12                     ;function 12
              mov cx,11                     ;subroutine call mask
              mov dx,offset mouse           ;point ES:DX to subroutine
              int 51                        ;pass information to mouse driver
;
;Terminate but leave the user-defined subroutine resident in memory.
;
              lea dx,initialize             ;point DX to end of resident code
              int 27h                       ;terminate-but-stay-resident
initialize    endp
;
code          ends
              end begin
