home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / mousecur.asm < prev    next >
Assembly Source File  |  1989-09-20  |  13KB  |  463 lines

  1. ;MOUSECURsor for Microsoft Mouse drivers - 9/87, upgraded 9/89
  2. ;Based on Jeff Prosise's MOUSEKEY.
  3. ;------------------------------------------------------------
  4. ; Microsoft MOUSE.COM or MOUSE.SYS, or a compatible driver must be installed.
  5. ; Works with the Mouse Systems MSMOUSE driver, but takes less total RAM.
  6. ; MOUSER works with ANY PROGRAM that accepts the cursor keys.
  7. ; Mouse speed and buttons can be programmed.
  8. ; The cursor keys continue to work as usual.  Programs with mouse drivers work
  9. ; independently of MOUSER.
  10. ; -------------------------------------------------------------------------- 
  11. ;            PARAMETERS
  12. ; MOUSER Hn Vn Lnn Mnn Rnn ?
  13. ;    ? = help (also appears if invalid command line params are entered)
  14. ;    Hn, Vn  n=1 to 9 - sets Horizontal or Vertical cursor speed
  15. ;    Lx, Mx, Rx - x=character or 2-digit decimal ASCII value:
  16. ;        Left, Middle, or Right button values
  17. ;        Digit values above 31 are treated as 'extended' keys.
  18. ;    Params are all optional, in any order, with any delimiters.
  19. ; -------------------------------------------------------------------------- 
  20. ;            ABOUT TSR AND RELOADING
  21.  
  22. ; Only one copy of MOUSER ever loads; after that, only the parameters
  23. ; are updated whenever the program is run.
  24. ; Some programs disable MOUSER; you can put MOUSER in the application's
  25. ; .BAT startup file, after the application program, to turn the mouse back on.
  26. ; Programs (like ACAD) with internal mouse drivers are commonly guilty of this.
  27. ; -------------------------------------------------------------------------- 
  28.  
  29. cr        equ    0Dh
  30. lf        equ    0Ah
  31.  
  32. code    segment byte public 'code'
  33.     assume cs:code, ds:code, es:code
  34.  
  35.     org    100h
  36.  
  37. Start:    jmp    Install
  38.  
  39. ResFinder    db    'MOUSER CODE'    ;Used to determine if MOUSER is resident
  40. vdelay        db    8        ;vertical divider (set by Vn)
  41. hdelay        db    8        ;horizontal divider (set by Hn)
  42. lkey        dw    0Dh        ;keycode for left button (set by Lnn)
  43. rkey        dw    1Bh        ;keycode for right button (set by Rnn)
  44. mkey        dw    5200h        ;keycode for middle button (set by Mnn)
  45.  
  46. vcount        dw    0        ;vertical mickeys since last update
  47. hcount        dw    0        ;horizontal
  48. UpDnPointer    dw    0
  49. LeRiPointer    dw    0        ;keycode below is at 011Eh in code
  50. keycode        db    4Dh,4Bh,50h,48h    ;codes for rt/left/dn/up cursor keys
  51.  
  52. ;------------------------------------------------------------------------------
  53. ;This routine gets a FAR CALL from the Microsoft driver when the mouse is
  54. ; moved or a button is pressed.
  55.  
  56. mouse:    push    ds
  57.     mov    dx,cs
  58.     mov    ds,dx
  59.     mov    dx,lkey
  60.     test    ax,2            ;bit 1, left button pressed ?
  61.     jnz    PutAndRet        ;yes, jump
  62.     mov    dx,rkey
  63.     test    ax,8            ;bit 3, right button ?
  64.     jnz    PutAndRet
  65.     mov    dx,mkey
  66.     test     ax,32            ;bit 5, middle button ?
  67.     jz    Move            ;no, must be mouse move
  68. PutAndRet:
  69.     mov    ax,dx
  70.     call    PutCode    
  71. MouseRet:
  72.     pop    ds
  73.     retf
  74.  
  75. ; - - - - - - - - - - - - - - - - - - - - - - - -
  76. ;Move the cursor.
  77. ;hdelay & vdelay are input as Hn Vn params, 1-slow to 8-fast, and converted
  78. ;for decrementing to divide by 128-slow to 1-fast.  It skips that number of
  79. ; mickeys (mouse increments) before responding.
  80. Move:    mov    ax,0Bh            ;read mouse motion counters
  81.     int    33h            ; CX=hor, DX=vert count
  82.     mov    LeRiPointer,0        ;point to Right keycode
  83.     mov    UpDnPointer,2        ;point to Down keycode
  84. ;accumulate motion, use totals.  No total exceeds +/- 32K.
  85.     add    hcount,cx
  86.     jno    NoHorOflo
  87.     jns    HorPos
  88.     mov    hcount,-32768
  89. HorPos:
  90.     mov    hcount,32767
  91. NoHorOflo:
  92.     add    vcount,dx
  93.     jno    NoVertOflo
  94.     jns    VertPos
  95.     mov    vcount,-32768
  96. VertPos:
  97.     mov    vcount,32767
  98. NoVertOflo:
  99.     cmp    vcount,0        ;vertical count positive?
  100.     jge    VDirSet
  101.     inc    UpDnPointer        ;point to Up code
  102. VDirSet:
  103.     cmp    hcount,0        ;horizontal count positive?
  104.     jge    DivideEm
  105.     inc    LeRiPointer        ;point to Left code
  106. ; Now the pointers point to the proper key code for the accumulated motion.
  107. ; The counts still are signed.
  108. ;Ideally, this would alternate hor & vert codes for diagonal moves.
  109. DivideEm:
  110.     mov    ax,vcount
  111.     cwd                ;extend AX to DX:AX
  112.     mov    cl,vdelay
  113.     xor    ch,ch
  114.     idiv    cx
  115.     mov    vcount,dx        ;signed remainder
  116.     mov    cx,ax            ;CX has no. of codes to insert, signed
  117.     or    cx,cx
  118.     jz    DoHor
  119.     jns    VertNotNeg
  120.     neg    cx
  121. VertNotNeg:
  122.     mov    bx,UpDnPointer
  123.     mov    ah,ds:[bx+keycode]
  124.     call    MovePut
  125. ;now do the same for horiz motion
  126. DoHor:    mov    ax,hcount
  127.     cwd
  128.     mov    cl,hdelay
  129.     xor    ch,ch
  130.     idiv    cx
  131.     mov    hcount,dx        ;signed remainder
  132.     mov    cx,ax
  133.     or    cx,cx            ;filter out zero to insert
  134.     jnz    HorSome
  135.     jmp    MouseRet
  136.  
  137. HorSome:
  138.     jns    HorNotNeg
  139.     neg    cx
  140. HorNotNeg:
  141.     mov    bx,LeRiPointer
  142.     mov    ah,ds:[bx+keycode]    ;get keycode from table
  143.     call    MovePut
  144.     jmp    MouseRet
  145.  
  146. MovePut:
  147.     xor    al,al            ;zero AL for extended keycode
  148. PutLoop:
  149.     call    PutCode
  150.     loop    PutLoop            ;sets CX=1 if buffer full, so will exit
  151.     ret
  152.  
  153. ; - - - - - - - - - - - - - - - - - - - - - - - -
  154. ;Put the keycode in AX into the keyboard buffer.
  155. PutCode:
  156.     push    ds
  157.     push    bx
  158.     mov    bx,40h            ;point DS to BIOS data area
  159.     mov    ds,bx
  160.     cli                ;disable interrupts
  161.     mov    bx,ds:[1Ch]        ;buffer tail
  162.     mov    dx,bx
  163.     add    dx,2            ;calculate next buffer position
  164.     cmp    dx,ds:[82h]        ;did we overshoot the buffer end?
  165.     jnz    insert1            ;no, continue
  166.     mov    dx,ds:[80h]        ;yes, wrap around to buffer start
  167. insert1:
  168.     cmp    dx,ds:[1Ah]        ;buffer head - is the buffer full?
  169.     jnz    DoInsert        ;no, do it
  170.     mov    cx,1            ;to exit calling loop
  171.     jmp    InsDone
  172.  
  173. DoInsert:
  174.     mov    ds:[bx],ax
  175.     mov    bx,dx            ;advance &
  176.     mov    ds:[1Ch],bx        ; store new pointer
  177. InsDone:
  178.     sti
  179.     pop    bx
  180.     pop    ds
  181.     ret
  182.  
  183. ;- - - - - - - end of resident portion - - - - - - -
  184.  
  185. Banner    db    cr,lf,'MOUSECUR 10/87 by Paul Noeldner, Madison, WI'
  186.     db    ' - - - hacked by J. E. Arkay 9/89'
  187.     db    cr,lf,'$'
  188. helpmsg    db    'Cursor enabler for Microsoft Mouse drivers.'
  189.     db    cr,lf,lf
  190.     db    'You can set the speed for easy pointing and the buttons for common keys.'
  191.     db    cr,lf
  192.     db    ' Put it in .BAT files, to set it up for your applications.'
  193. jnkhelp    db    cr,lf,lf
  194.     db    'Example:',cr,lf
  195.     db    ' MOUSECUR H5 V5 L13 R27 M82   shows default parameters.',cr,lf
  196.     db ' MOUSECUR H1 V2 M/            Slower cursor (for 123-style menus)'
  197.     db    cr,lf
  198.     db ' MOUSECUR V7 L73 M81 R27      Faster with PGUP/PGDN (for browsing)'
  199.     db    cr,lf,lf
  200.     db '    Hn, Vn      Horizontal, Vertical speed 1-8 (default 5 if not entered)'
  201.     db    cr,lf
  202.     db '    Lx, Mx, Rx  Button characters or decimal ASCII key codes'
  203.     db    cr,lf
  204.     db '    All params are optional, in any order, with any delimiter.'
  205.     db    cr,lf
  206.     db '    ASCII values over 31 decimal are taken to be extended keys.'
  207.     db    cr,lf,lf
  208.     db ' Commonly used keys (see a BASIC manual for more):'
  209.     db    cr,lf
  210.     db '03 - CTRL-C   09 - TAB     13 - RETURN   27 - ESC'
  211.     db    cr,lf
  212.     db '71 - HOME     73 - PGUP    78 - GRAY +   79 - END      81 - PGDN'
  213.     db    cr,lf
  214.     db '82 - INSERT   83 - DELETE        59 THRU 68 - F1 THRU F10'
  215.     db    cr,lf,lf,'$'
  216.  
  217. NoDriverMsg      db    cr,lf,' DRIVER MISSING: Install MOUSE.SYS, MOUSE.COM,'
  218.         db    ' MSMOUSE.COM, etc.',cr,lf,lf,'$'
  219.  
  220. junkmsg        db    cr,lf,' INVALID PARAMETER - CHECK THIS SCREEN',7,'$'
  221.  
  222. loadmsg        db    'Mouse Cursor Installed',cr,lf,lf,'$'
  223.  
  224. AdjustedMsg    db    'Mouse Parameters Adjusted ',cr,lf,lf,'$'
  225.  
  226. endparm     dw    81h        ;offset of end of params
  227. posted        db    'N'        ;is MOUSER already loaded ?
  228. DigitFlag    db    'N'        ;found a digit in command line
  229.  
  230. Install:
  231.     mov    dx,OFFSET Banner
  232.     mov    ah,9
  233.     int    21h
  234.     mov    ax,0        ;check Microsoft driver is installed and reset.
  235.     int    33h
  236.     or    ax,ax
  237.     jnz    DrvrOK            ;AX=0FFFFh if installed OK
  238.     mov    dx,OFFSET NoDriverMsg
  239.     jmp    MsgExit
  240.  
  241. DrvrOK:    call    parms            ;process command line params
  242.     call    Find            ;if MOUSECUR is resident, update params
  243.     cmp    posted,'Y'
  244.     jnz    TSR            ;if not, install this copy
  245.     mov    dx,OFFSET AdjustedMsg
  246.     jmp    MsgExit
  247.  
  248. TSR:    mov    ah,9
  249.     mov    dx,OFFSET loadmsg
  250.     int    21h
  251.     mov    ax,0Ch            ;activate Microsoft driver
  252.     mov    cx,101011b  ;'call mask'- call if mouse moved, or button press
  253.     mov    dx,OFFSET mouse        ;point ES:DX to our routine
  254.     int    33h            ;pass address to mouse driver
  255. ;de-allocate the Environment Block, we don't need it
  256. ; NOTE: This sometimes leaves a uselessly small unused Block
  257.     push    es
  258.     xor    ax,ax
  259.     xchg    ax,word ptr CS:2Ch    ;Environment Block addr in the PSP
  260.     or    ax,ax
  261.     jz    GoRes            ;skip it if there is no Env
  262.     mov    es,ax
  263.     mov    ah,49h            ;free allocated RAM
  264.     int    21h
  265. GoRes:    pop    es
  266.     mov    dx,offset Banner    ;bytes to stay resident
  267.     add    dx,15            ;allow for fractional para
  268.     mov    cl,4
  269.     shr    dx,cl            ;paras to stay resident
  270.     mov    ax,3100h        ;go TSR
  271.     int    21h
  272. ; - - - - - - - - - - - - - - - - - - -
  273.  
  274. ;Process command line params (if any)
  275. parms:    mov    si,80h        ;point at input param length in PSP
  276.     mov    ah,0
  277.     mov    al,[si]        ;length of params
  278.     add    ax,80h        ;compute end of params
  279.     mov    endparm,ax    ;remember it
  280.     inc    si        ;skip initial space in input params
  281.  
  282. parmloop:
  283.     inc    si
  284.     cmp    si,endparm    ;at end of params ?
  285.         jle    parse        ;if not, process it
  286.     ret            ;if so, done with setup
  287.  
  288. parse:    mov    al,[si]        ;get next character
  289.         cmp    al,' '        ;skip blanks
  290.     jz    parmloop
  291.     cmp    al,'/'        ;skip slashes
  292.     jz    parmloop
  293.     cmp    al,','        ;skip commas
  294.     jz    parmloop
  295. help:    cmp    al,'?'        ;show help?
  296.     jnz    case
  297.     mov    dx,OFFSET helpmsg
  298. MsgExit:
  299.     mov    ah,9
  300.     int    21h
  301.     mov    ax,4C01h    ;exit w/Errorlevel = 1
  302.     int    21h
  303.  
  304. case:     cmp al,91        ;upper case?
  305.     jl  upper
  306.           sub al,32        ;convert lower to upper case   
  307.  
  308. upper:    call parmcheck        ;see if H, V, L, R 
  309.     jmp parmloop        ;continue parsing
  310.  
  311. ;Check for Horizontal and Vertical Speed, Left/Right/Both button control values
  312. parmcheck:
  313.     cmp    al,'H'        ;horizontal speed param ?
  314.     jnz    parmv
  315.     call    digedit        ;next byte to AL
  316.         cmp    DigitFlag,'Y'
  317.         jnz    junk        ;error if not
  318.     cmp    al,8
  319.     ja    junk
  320.     call    CvtSpeed
  321.     mov    hdelay,ah
  322.     ret            ;back to parsing params
  323.  
  324. parmv:    cmp    al,'V'        ;vertical speed param ?
  325.     jnz    parml
  326.     call    digedit        ;next byte to AL
  327.     cmp    DigitFlag,'Y'
  328.     jnz    junk        ;error if not
  329.     cmp    al,8
  330.     ja    junk
  331.     call    CvtSpeed
  332.     mov    vdelay,ah
  333.     ret
  334.  
  335. CvtSpeed:
  336.     mov    ah,80h
  337.     sub    al,1        ;DEC AL will not set the C flag !!
  338.     jc    CvtRet        ;if speed input was 0, use speed 1
  339.     mov    cl,al
  340.     shr    ah,cl        ;each number is a factor of 2
  341. CvtRet:    ret
  342.  
  343. parml:    cmp    al,'L'        ;left button param ?
  344.     jnz    parmr
  345.     call    dighex        ;get 2 ASCII bytes to AX
  346.     mov    lkey,ax        ;left button key code
  347.     ret
  348.  
  349. parmr:    cmp    al,'R'        ;right button param ?
  350.     jnz    parmb
  351.     call    dighex        ;get 2 ASCII bytes to AX
  352.     mov    rkey,ax        ;right button key code
  353.     ret
  354.  
  355. parmb:    cmp    al,'M'        ;middle button param ?
  356.     jnz    junk        ;error if not
  357.     call    dighex        ;get 2 ASCII bytes to AX
  358.     mov    mkey,ax        ;both buttons key code
  359.     ret
  360.  
  361. junk:    mov    dx,OFFSET junkmsg
  362.     mov    ah,9
  363.     int    21h
  364.     mov    dx,OFFSET jnkhelp    ;help, error message for invalid parms
  365.     jmp    MsgExit
  366.  
  367. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  368. ;Check for other copies of this program in memory by walking MCB's.
  369. ;See HOTBOOT3 for how to avoid the copy in the disk buffer with shorter code.
  370. ;If MOUSER is already resident, params are updated in that copy of the program.
  371. Find:    push    ax
  372.     push    bx
  373.     push    cx
  374.     push    dx
  375.     push    es
  376.     cld                ;compare UPward
  377.     mov    ah,52h            ;get DOS list of lists
  378.     int    21h            
  379.     mov    bx,es:[bx-2]        ;starting MCB seg address
  380.     inc    bx            ;for first DEC below
  381. FindLoop:
  382.     dec    bx
  383.     mov    es,bx            ;point to the MCB
  384.     add    bx,es:[3]
  385.     inc    bx            ;length + 1 points next MCB
  386.     inc    bx            ;and 1 more points next block
  387.     mov    es,bx
  388.     mov    ax,cs
  389.     cmp    bx,ax            ;BX and ES up to present CS ?
  390.     jae    NoCopies
  391.     mov    si,offset ResFinder    ;point DS:SI to our signature
  392.     mov    di,si            ;look the same place in both segs
  393.     mov    cx,11            ;length of 'MOUSER CODE'
  394.     repz    cmpsb            ;DS:[SI] - ES:[DI] and inc SI & DI
  395.     jnz    FindLoop        ;if not same, check next block
  396. ;Post params in current resident MOUSER
  397.     mov    posted,'Y'        ;flag we've done this
  398.     mov    al,vdelay        ;copy from this loaded copy
  399.      mov    es:vdelay,al        ; to resident copy
  400.     mov    al,hdelay
  401.     mov    es:hdelay,al
  402.     mov    ax,lkey
  403.     mov    es:lkey,ax
  404.     mov    ax,rkey
  405.     mov    es:rkey,ax
  406.     mov    ax,mkey
  407.     mov    es:mkey,ax
  408. ;Re-activate the Microsoft driver  
  409.     mov    ax,0Ch            ;set driver active
  410.     mov    cx,00101011b    ;'call mask', move or button press (not release)
  411.     mov    dx,offset mouse        ;ES:DX points installed Mouse routine
  412.     int    33h
  413. NoCopies:
  414.     pop    es
  415.     pop    dx
  416.     pop    cx
  417.     pop    bx
  418.     pop    ax
  419.     ret
  420.  
  421. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  422. ;ASCII digits to hex routine
  423. dighex:    call    digedit        ;get next byte into AL
  424.         cmp    DigitFlag,'Y'
  425.     jz    digcon
  426.     ret            ;otherwise got literal in AX
  427.  
  428. digcon:    mov    bx,ax        ;save hi digit
  429.     call    digedit        ;get next byte
  430.     cmp    DigitFlag,'Y'
  431.     jz    ItsOK
  432.     jmp    junk        ;error if not
  433. ItsOK:    xchg    ax,bx        ;hi byte to AX, lo byte to BX
  434.     mov    cx,10
  435.     mul    cx        ;AX=hi byte times 10
  436.     add    ax,bx        ;now AX=value
  437.         cmp    al,' '        ;is number < 20h ?
  438.     jl    setok        ;yes, set as is
  439.     mov    ah,al        ;make higher nos the high byte, and
  440.     xor    al,al        ; null the low byte for extended keycode
  441. setok:    ret
  442.  
  443. ;Get value of ASCII digit or literal into AL with AH=0
  444. digedit:
  445.     mov    DigitFlag,'N'    ;assume literal, not digit
  446.     inc    si            
  447.     mov    al,[si]        ;get next byte
  448.     mov    ah,al        ;save literal value
  449.     sub    al,30h        ;convert digit to hex
  450.     jl    liter        ;if < 0, is literal
  451.     cmp    al,9
  452.     jg    liter        ;if not digit, is literal
  453.     mov    DigitFlag,'Y'
  454.     xor    ah,ah
  455.     ret
  456.  
  457. liter:    mov    al,ah        ;use literal character
  458.     xor    ah,ah
  459.     ret            ;back to param scan
  460.  
  461. code    ends
  462.         end    Start
  463.