        PAGE    ,132
        NAME    VMINT33
        TITLE   Virtual Mouse Device Driver Int 33h Support


;*************************************************************************
;*
;* SOURCE FILE NAME = VMINT33.ASM
;*
;* DESCRIPTIVE NAME = Virtual Mouse Device Driver Int 33h Support
;*
;* Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
;*             Copyright Microsoft Corporation, 1990
;*             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
;*             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
;*             RESTRICTED MATERIALS OF IBM
;*             IBM CONFIDENTIAL
;*
;* VERSION =   V2.0
;*
;* DATE        07/28/91
;*
;* DESCRIPTION This module contains the Int 33h and BASIC router support
;*             that must run in V86 mode.
;*
;* FUNCTIONS
;*
;* ENTRY POINTS:
;*
;* DEPENDENCIES:
;*
;* NOTES
;*
;*
;* STRUCTURES
;*
;* EXTERNAL REFERENCES
;*
;* EXTERNAL FUNCTIONS
;*
;* CHANGE ACTIVITY =
;*  DATE      FLAG        APAR   CHANGE DESCRIPTION
;*  --------  ----------  -----  --------------------------------------
;*  mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*  01/30/89  @V2.0JTP01  JTP        Created.
;*  06/10/91  @V2.0JMR01  Jeff Muir  Modified for DOS BOOT
;*  01/18/93  @V2.0WMN01  W. Madden  Use int 2f instead of int 66 for VM boot
;*  00/00/00  @V2.0RAR01  60491
;****************************************************************************

INCL_NONE equ   1
INCL_VDH  equ   1

        .xlist

;*
;*       DEBUG=1
;*       include vmdp.inc
;*

        include mvdm.inc
        .list

        .8086                       ; This is run in real mode

;*
;* defines for BASIC entry point
;*

pAX     equ     [bp+12]
pBX     equ     [bp+10]
pCX     equ     [bp+8]
pDX     equ     [bp+6]

ARPLCODE        equ     063h       ; APRL Opcode value
VDDINTERFACE    equ     02fh       ; Int vector for VDD interface


;/***************************************************************************
;*
;* FUNCTION NAME =  vmInt33Router()
;*
;* DESCRIPTION   =  VDM router to process BASIC mouse calls
;*
;*   This function must be installed in every VDM in order to route BASIC
;*   mouse function calls to our Int 33h hook (above).  As part of VDM
;*   creation, VMCreate hooks Int 33h and then takes the breakpoint address
;*   that VDMM installed in the VDM's vector 33h and stuffs it into the code
;*   below (at vpInt33BP), copies this function into the VDM, and then
;*   edits the VDM's vector 33h to point to it.
;*
;*   Note that the code is written using 32-bit instructions, because we want
;*   to assemble it in a 32-bit segment in order to successfully link it
;*   with the rest of the VMD, and because we cannot have operand/address size
;*   overrides on ANY of the instructions, since they must run in a VDM (that
;*   is, in V86 mode).  Because it is not executable in the context of the
;*   VDD, I have defined it in the VDD's global *DATA* segment.  Be sure to
;*   keep the code totally relocatable, without any segment or offset fixups
;*   for either linker or loader to resolve (in other words, make sure that the
;*   MASM listing file shows no unresolved values).
;*
;* INPUT         =  Addresses of Int 33h parameters pushed on stack
;*
;* OUTPUT        =  Results replaced in parameters
;* USES             16-bit small-model PASCAL calling/register conventions
;*
;* CONTEXT          VDM Task-time, in V86 mode
;*
;* RETURN-NORMAL =
;*
;*
;* RETURN-ERROR  =
;*
;*
;**************************************************************************/
;*
;*  The next few lines are used by an rexx script.
;*
;*  #### HEADERFILE=vmint33.h
;*  #### ENTRYPOINT=vmInt33Router
;*  #### LENGTH=VMInt33RouterLength
;*
;*  #### BEGIN EXTRACTION
;*   It is used by n rexx script to convert the listing file into an .ASM file.
;******************************************************************************

CODE    SEGMENT BYTE PUBLIC 'CODE'

        assume cs:CODE,ds:CODE,es:CODE

ifdef MOUSECOM                 ; if we are building MOUSE.COM, start at 100h
        org 100h
MOUSEINIT  proc   far
        jmp    near ptr MOUSEINIT2  ; moved the code above TSR line
MOUSEINIT  endp
endif
ifndef MOUSECOM
        org 0h                 ; otherwise start at offset 0h
MOUSEINIT proc  far
MOUSEINIT endp
endif


vmInt33Router proc far
;*       jmp     far ptr 0000:0000      ; hand-assemble it
         db      0EAh                   ; @V2.0JMPO1 FAR  opcode
patch1   LABEL byte                     ; #### LABEL=VMInt33BP
vpInt33BP DD    000000000h              ; @V2.0JMP01 portion (to be patched)
vmInt33Router  endp


vmInt33RouterEntry proc far
enterrouter  LABEL byte                 ; #### LABEL=ROUTER_ENTRYOFFSET
        jmp    short vmInt33Router      ; normal Int 33h goes to special jump
vmInt33RouterEntry endp


vmInt33RouterBasicEntry proc far

;*
;*       ArgVar  pAX,USHORT
;*       ArgVar  pBX,USHORT
;*       ArgVar  pCX,USHORT
;*       ArgVar  pDX,USHORT
;*

        push    bp
        mov     bp,sp

        mov     si,pAX                  ;BASIC router entry point must begin
        mov     ax,[si]                 ;exactly TWO bytes after router entry
        mov     si,pBX
        mov     bx,[si]
        mov     si,pCX
        mov     cx,[si]
        mov     si,pDX
        mov     dx,si
        cmp     ax,9                    ;if function call 9..
        jz      short vmrouter_setcur   ;..we just want the address
        cmp     ax,18
        jz      short vmrouter_setcur
        cmp     ax,12                   ;or function call 12...
        jz      short vmrouter_setcur   ;..we just want the address
        cmp     ax,20                   ;or function call 20...
        jne     short vmrouter_getdx    ;branch if not function 20
        mov     es,bx                   ;es <- bx
        or      bx,bx                   ;if bx is 0, es <- ds
        jnz     short vmrouter_setcur   ;branch if bx <> 0
        push    ds                      ;es <- ds
        pop     es
        jmp     short vmrouter_setcur   ;..we just want the address in dx

vmrouter_getdx:
        mov     dx,[si]                 ;get value at dx
        cmp     ax,16                   ;conditional off call?
        jnz     short vmrouter_setcur   ;no, call the mouse driver
        mov     cx,[si]                 ;load the two corners
        mov     dx,[si+2]
        mov     di,[si+6]
        mov     si,[si+4]

vmrouter_setcur:
        push    ax                      ;save command

        pushf                           ;simulate an Int 33h
        cli
        call    dword ptr cs:[vpInt33BP]

        pop     si                      ;pop command into unused register
        cmp     si,20                   ;check if swap vector call
        jne     short vmrouter_skipes   ;branch if not a swap vector call
        mov     bx,es                   ;bx <- es
        push    ds                      ;es <- ds
        pop     es

vmrouter_skipes:
        cmp     si,9                    ;check if load cursor command
        jz      short vmrouter_nodx
        cmp     si,12
        jz      short vmrouter_nodx
        cmp     si,16
        jz      short vmrouter_nodx
        mov     si,pDX
        mov     [si],dx

vmrouter_nodx:
        mov     si,pCX
        mov     [si],cx
        mov     si,pBX
        mov     [si],bx
        mov     si,pAX
        mov     [si],ax
        pop     bp
        retf    8
vmInt33RouterBasicEntry   endp


VMEnd  label    byte                ; This line is a dummy to keep
                                    ; the REXX happy with the byte length count
                                    ; PUT ALL DATA/CODE ABOVE THIS LABEL

;*
;* #### END EXTRACTION
;*


ifdef  MOUSECOM

VMName db       'VMOUSE$',0

pfnVMOUSE dd  0                     ; entry to VMOUSE VDD
MOUSEINIT2  proc far

        push    cs
        pop     ds

;*
;* @V2.0RAR01  push    es
;* @V2.0RAR01  xor     ax,ax
;* @V2.0RAR01  mov     es,ax
;* @V2.0RAR01  mov     di,VDDINTERFACE*4       ; verify interface is present
;* @V2.0RAR01  les     di,dword ptr es:[di]
;* @V2.0RAR01  cmp     byte ptr es:[di],ARPLCODE
;* @V2.0RAR01  pop     es
;* @V2.0RAR01  jz      OS2Present
;*

        mov     ax,4010h                                            ;@V2.0RAR01
        int     VDDINTERFACE         ; verify interface is present  ;@V2.0RAR01
        cmp     ax,4010h                                            ;@V2.0RAR01
        jne     OS2Present                                          ;@V2.0RAR01
NoOS2:
                                     ; output error message
        mov     si,offset TXT_MSG_MOUSE_NEEDS_OS2
        call    msgprint
        mov     ax,4c02h             ; terminate program with error
        int     21h

OS2Present:

;*
;* @V2.0RAR01  mov     si,offset VMName    ;
;* @V2.0RAR01  xor     ax,ax           ; function zero determines VDD presence
;* @V2.0RAR01  int     VDDINTERFACE
;* @V2.0RAR01  jnc     VDDPresent          ; if no error, continue
;*

        mov     si,offset VMName                                    ;@V2.0RAR01
        xor     di,di                                               ;@V2.0RAR01
        push    es                                                  ;@V2.0RAR01
        mov     es,di                                               ;@V2.0RAR01
        mov     ax,04011h                                           ;@V2.0RAR01
        int     VDDINTERFACE                                        ;@V2.0RAR01
        mov     ax,es                                               ;@V2.0RAR01
        or      ax,di                                               ;@V2.0RAR01
        mov     ax,es                 ; AX:DI = VMOUSE entry point  ;@V2.0RAR01
        pop     es                                                  ;@V2.0RAR01
        jnz     VDDPresent                                          ;@V2.0RAR01
NoVDD:
                                      ;output error message
        mov     si,offset TXT_MSG_MOUSE_NEEDS_VMOUSE
        call    msgprint
        mov     ax,4c03h              ; terminate program with error
        int     21h

VDDPresent:
        mov     word ptr cs:[pfnVMOUSE],di                          ;@V2.0RAR01
        mov     word ptr cs:[pfnVMOUSE+2],ax                        ;@V2.0RAR01

;@V2.0RAR01  mov     si,offset VMName

        mov     di,offset vpInt33BP
        mov     ax,0100h              ; get breakpoint CMD
        call    cs:[pfnVMOUSE]        ; call VMOUSE                 ;@V2.0RAR01

;@V2.0RAR01  int     VDDINTERFACE

        push    es                    ; Install Int 33 hook
        xor     ax,ax
        mov     es,ax
        mov     word ptr es:[4*33h],offset vmInt33RouterEntry
        mov     word ptr es:[4*33h +2],cs
        pop     es

                                      ; output header message
        mov     si,offset TXT_MSG_VMBOOT_MOUSE_BANNER
        call    msgprint

        mov     ax,offset VMEnd       ; get the ending offset
        shr     ax,1                  ; and convert to paragraphs
        shr     ax,1
        shr     ax,1
        shr     ax,1
        inc     ax
        mov     dx,ax                 ; terminate and stay resident
        mov     ax,3100h
        int     21h
MOUSEINIT2  endp

;*
;*
;* msgprint - small msgretriever print routine
;*
;*   INPUT - (DS:SI) message (length message)
;*

msgprint   proc   near
        push    ax
        push    si
        push    dx
        mov     ax,word ptr ds:[si]   ; get the length
        inc     si                    ; move DX to text area
        inc     si                    ;
        mov     dx,si
        add     si,ax                 ; point SI to end of text
        mov     byte ptr ds:[si],'$'  ; add string terminate
        mov     ah,09h
        int     21h
        pop     dx
        pop     si
        pop     ax
        ret
msgprint   endp
;*
;* include file generated on the fly by MSGPROF, MKMSGF
;*


include mouse.inc

endif

CODE    ends

        END     MOUSEINIT

