home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / fastbuff.asm < prev    next >
Assembly Source File  |  1987-11-29  |  32KB  |  939 lines

  1.                         page    66,132
  2. ;
  3. ;          FASTBUFF.ASM - Keyboard buffer resident utility.
  4. ;
  5. ;                        Version 2.0
  6. ;
  7. ;                   by: David Steiner
  8. ;                       [D.STEINER] on GEnie
  9. ;                       2035 J Apt. 6
  10. ;                       Lincoln, NE   68510
  11. ;                       (402) 475-0601
  12. ;
  13. ;       This is a fairly big update from version 1.0.  FASTBUFF now
  14. ;       handles Alt-keypad character entries correctly, plus fixes
  15. ;       these characters since many IBM clones generate incorrectly.
  16. ;
  17. ;       The way characters are restored to the system has been updated
  18. ;       also.  We no longer hook the Keyboard I/O interrupt, instead we
  19. ;       continuously keep the BIOS buffer full by filling it every time
  20. ;       the system timer clicks (Interrupt 1C).
  21. ;       This was done as an allowance for programs that bypass the BIOS
  22. ;       when doing character I/O.  It has the added benefit of allowing
  23. ;       FASTBUFF to be active when installed after other utilities that
  24. ;       hook into interrupt 16.
  25. ;
  26. ;       The only software compatibility problems that should arise will
  27. ;       be with other programs that hook the Keystroke interrupt and attempt
  28. ;       to insert characters directly into the BIOS keyboard buffer.
  29. ;       "Key-fake" utilities are an example of such programs.   If you
  30. ;       need to use such a program, it is best to deactivate FASTBUFF first.
  31.  
  32. cseg    segment
  33.         assume  cs:cseg, ds:cseg
  34.         org     100H
  35. start:
  36.         jmp     initialize
  37.  
  38. ;
  39. ;------ Old vector storage area
  40. ;
  41. oldint9         dd
  42. oldint10        dd
  43. oldint1C        dd
  44.  
  45. ;------ EQUATES
  46.  
  47. cr              equ     0DH
  48. lf              equ     0AH
  49.  
  50. ;------ BIOS buffer & otherstuff equates
  51.  
  52. BIOSdseg        equ     40H             ; BIOS data area segment
  53. BIOShead        equ     1AH             ; BIOS keyboard buffer head
  54. BIOStail        equ     1CH             ;  ""  tail
  55. BIOSaltbuff     equ     19H             ; Storage for Alt-keypad entries
  56.  
  57. BIOSbuffer      equ     1EH             ; BIOS keyboard buffer start
  58. BIOSendbuff     equ     3EH             ;   end
  59.  
  60. BIOSequipflags  equ     10H             ; BIOS equipment word address
  61. BIOScrtmodeset  equ     65H
  62. BIOSpalette     equ     66H
  63. equipmask       equ     0010H
  64. palettemask     equ     0FH
  65.  
  66. KBinport        equ     60H             ; Keyboard data port
  67. KBctrlport      equ     61H             ; Keyboard control port
  68. Altshift        equ     38H             ; ALT key scan code
  69.  
  70. ;------ BIOS shift status byte 1 & masks for action key combinations
  71.  
  72. BIOSshflags     equ     17H             ; First BIOS shift status byte
  73. ClrMask         equ     05H             ; Clear buffer key mask
  74. altmask         equ     08H             ; Bit set when Alt is being held down
  75.  
  76. ;------ FASTBUFF control key scan codes
  77.  
  78. fbctrlkey       equ     4CH             ; Scan code for "5" on keypad
  79.  
  80. fbonkey         equ     52H             ; Code for INS key
  81. fboffkey        equ     53H             ; Code for DEL key
  82. fbfast          equ     4EH             ; Code for keypad "+"
  83. fastrep         equ     2               ; Chars per click for fast rate
  84. fbslow          equ     4AH             ; Code for keypad "-"
  85. slowrep         equ     1               ; Chars per click for slow rate
  86.  
  87. ;------ BIOS break detection byte
  88.  
  89. BIOSbreak       equ     71H             ; Bit 7 of this byte indicates
  90. breakmask       equ     80H             ;  ctrl-break was pressed
  91.  
  92. ;------ Masks for altering bits in our status byte.
  93.  
  94. fbmask          equ     01H             ; Masks for FASTBUFF toggle
  95. repmask         equ     02H             ; On when we need to repeat a character
  96. scrmask         equ     04H             ; On while screen is active
  97. ctrlmask        equ     08H             ; On when [5] is being held down
  98. oldint9mask     equ     10H             ; On when processing char with old int9
  99. vidmask         equ     20H             ; Video blanking active?
  100.  
  101.         assume  ds:nothing
  102.  
  103. ;---------------------------- Int 09 --------------------------------------
  104. ;Keystroke Interrupt
  105. ;
  106. ;       Note that we always allow control to pass on to the old interrupt
  107. ;       9 handler.  We do, however, ignore the characters returned if one
  108. ;       of FASTBUFF's four command key combinations were detected.
  109. ;--------------------------------------------------------------------------
  110. newint9         proc    far
  111.         sti
  112.         push    ax
  113.         push    bx
  114.         push    cx
  115.         push    dx
  116.         push    es
  117.  
  118. ;------ This first section is code always executed by FASTBUFF
  119.  
  120.         and     cs:switches,not repmask ; Turn off repeat switch
  121.  
  122.         mov     bx,BIOSdseg             ; Set ES to BIOS data seg and
  123.         mov     es,bx                   ;   turn off break bit
  124.         and     byte ptr es:BIOSbreak,not breakmask
  125.  
  126.         mov     cx,cs:screendelay       ; Reset screen blank counter
  127.         mov     cs:scrcount,cx
  128.         test    cs:switches,scrmask     ; Check if video is blanked
  129.         jnz     skiprestore
  130.         call    restorescreen           ; If so turn it back on
  131. skiprestore:
  132.         in      al,KBinport             ; Get scan code from keyboard
  133.  
  134.         test    cs:switches,ctrlmask    ; Check if currently in control mode
  135.         jz      notcontrol
  136.  
  137. ;------ FASTBUFF control key check when keypad #5 is depressed
  138.  
  139.         cmp     al,fbctrlkey+80H         ; Check if control key was released
  140.         jne     notreleased
  141.         and     cs:switches,not ctrlmask ; Turn off control mode
  142.         jmp     callold9
  143. notreleased:
  144.         cmp     al,fbonkey
  145.         jne     k1
  146.         or      cs:switches,fbmask      ; Turn on FASTBUFF
  147.         jmp     clearall
  148. k1:
  149.         cmp     al,fboffkey
  150.         jne     k2
  151.         and     cs:switches,not fbmask  ; Turn off FASTBUFF
  152.         jmp     clearall
  153. k2:
  154.         test    byte ptr cs:switches,fbmask ; FASTBUFF on?
  155.         jz      notpressed
  156.  
  157.         cmp     al,fbfast
  158.         jne     k3
  159.         mov     cs:repchars,fastrep     ; Set fast repeat rate
  160.         jmp     reset
  161. k3:
  162.         cmp     al,fbslow
  163.         jne     notpressed
  164.         mov     cs:repchars,slowrep     ; Set slow repeat rate
  165.         jmp     reset
  166. clearall:
  167.         cli
  168.         mov     bx,es:BIOStail
  169.         mov     es:BIOShead,bx          ; Clear both keyboard buffers
  170.         mov     bx,cs:tail
  171.         mov     cs:head,bx
  172. reset:
  173.         cli
  174.         mov     bx,es:BIOStail          ; Allow old interrupt handler to
  175.         pushf                           ;   to see the keystroke entered,
  176.         call    oldint9                 ;   but ignore any output character.
  177.         mov     es:BIOStail,bx
  178.         sti
  179.         jmp     int9done
  180.  
  181. ;------ Not currently in control mode so check for other possibilities
  182.  
  183. notcontrol:
  184.         cmp     al,fbctrlkey            ; Check if our control key pressed
  185.         jne     notpressed
  186.         or      cs:switches,ctrlmask    ; Turn on control mode
  187. notpressed:
  188.  
  189. ;------ Finally we will check to see if FASTBUFF is active
  190.  
  191.         test    byte ptr cs:switches,fbmask ; FASTBUFF on?
  192.         jz      off1
  193.         cmp     al,37H                  ; If Shift-PrtSc is pressed then just
  194.         jne     on1                     ;    call old handler and exit
  195.         test    byte ptr es:BIOSshflags,03H
  196.         jz      on1
  197. off1:
  198.         pushf                           ; Not on so call old int9 and exit
  199.         call    oldint9
  200.         jmp     int9done
  201. on1:
  202.         cmp     al,altshift+80H         ; Check if Alt key released
  203.         jne     notalt
  204.         mov     ah,es:BIOSaltbuff       ; If so save alt-keypad character
  205.         jmp     callold9
  206. notalt:
  207.         mov     bh,es:BIOSshflags
  208.         and     bh,0FH
  209.         cmp     bh,clrmask              ; Clear key combination pressed?
  210.         jne     callold9
  211.         cli
  212.         mov     bx,es:BIOStail          ; Clear out buffers
  213.         mov     es:BIOShead,bx
  214.         mov     bx,cs:tail
  215.         mov     cs:head,bx
  216.         sti
  217.  
  218. ;------ Let the old BIOS handler determine what the ASCII or extended
  219. ;       character code should be.
  220.  
  221. callold9:
  222.         or      cs:switches,oldint9mask ; Set bit so we don't update BIOS buff
  223.         mov     bx,es:BIOStail          ; Make old int 9 do the dirty work
  224.         pushf
  225.         call    oldint9
  226.         mov     dx,es:[bx]              ; Store new char in DX
  227.         mov     cx,es:BIOStail
  228.         mov     es:BIOStail,bx
  229.         and     cs:switches,not oldint9mask
  230.  
  231.         test    byte ptr es:BIOSbreak,breakmask
  232.         jz      checknew
  233.         cli
  234.         mov     es:BIOShead,bx
  235.         mov     bx,cs:head              ; Break detected, clear our buffers
  236.         mov     word ptr cs:[bx],0      ;   and output dummy character
  237.         call    incbuff
  238.         mov     cs:tail,bx
  239.         sti
  240.         jmp     int9done
  241. checknew:
  242.         cmp     bx,cx
  243.         jne     newchar
  244.         mov     cs:lastchar,0FFFFH      ; Set non-typeable char as lastchar
  245.         jmp     int9done
  246.  
  247. newchar:
  248.         cmp     al,altshift+80H         ; Check if Alt key released
  249.         jne     putin
  250.         mov     dl,ah                   ; Fix entered character with keypad
  251.         mov     dh,0                    ; Scan code = 0
  252. putin:
  253.         call    newinchar
  254. int9done:
  255.         pop     es
  256.         pop     dx
  257.         pop     cx
  258.         pop     bx
  259.         pop     ax
  260.         iret
  261. newint9         endp
  262.  
  263. ;------ NewInChar -  Take char from BIOS buffer and insert it into ours,
  264. ;                    then set repeat switch accordingly.
  265. ;
  266. ;               ES contains BIOSdseg
  267. ;               DX contains character that was return by old int 9
  268.  
  269. newinchar       proc    near
  270.         push    si
  271.  
  272.         cmp     dx,cs:lastchar
  273.         je      indone                  ; Ignore character if it was from STD
  274.                                         ;   repeat function
  275.         mov     cs:lastchar,dx
  276.         mov     bh,cs:startdelay        ; Set start delay for repeat function
  277.         mov     cs:repcount,bh
  278.         mov     bx,cs:tail
  279.         mov     si,bx                   ; Save address where char will go
  280.         call    incbuff
  281.         cmp     bx,cs:head
  282.         jne     storchar
  283.         call    errbeep
  284.         jmp     indone
  285. storchar:
  286.         cli
  287.         mov     cs:[si],dx              ; Store character
  288.         mov     cs:tail,bx              ; Store new tail value
  289.         sti
  290. indone:
  291.         cmp     dh,0                    ; Scan code = 0 if entered on keypad
  292.         jne     switchon
  293.         test    byte ptr es:BIOSshflags,02H ; Allow chars entered via the
  294.         jz      reallydone              ;   keypad to repeat if the user is
  295. switchon:                               ;   holding down the Left Shift key.
  296.         or      cs:switches,repmask
  297. reallydone:
  298.         pop     si
  299.         ret
  300. newinchar       endp
  301.  
  302. ;------ ErrBeep - Keyboard full error beep, from ROM BIOS listing
  303.  
  304. errbeep proc    near
  305.         push    ax
  306.         push    bx
  307.         push    cx
  308.  
  309.         mov     bx,030H                 ; Cycles for 1/16 second tone
  310.         in      al,61H                  ; Get keyboard ctrl information
  311.         push    ax                      ; Save it
  312.  
  313. beepcycle:
  314.         and     al,0FCH                 ; Turn off timer gate & spkr data
  315.         out     61H,al                  ; Output to control
  316.         mov     cx,48H                  ; Half cycle time for tone
  317. l1:     loop    l1                      ; Speaker off
  318.         or      al,2                    ; Turn on speaker bit
  319.         out     61H,al                  ; Output to control
  320.         mov     cx,48H                  ; Set up count
  321. l2:     loop    l2                      ; another half cycle
  322.         dec     bx                      ; Total time count
  323.         jnz     beepcycle               ; Do another cycle
  324.  
  325.         pop     ax                      ; Recover control
  326.         out     61H,al                  ; Output the control
  327.  
  328.         pop     cx                      ; Recover registers
  329.         pop     bx
  330.         pop     ax
  331.         ret
  332. errbeep endp
  333.  
  334. ;---------------------------- Int 10 --------------------------------------
  335. ;Video I/O
  336. ;--------------------------------------------------------------------------
  337. newint10        proc    far
  338.         sti
  339.         cmp     ah,0FAH                 ; Return value to indicate FASTBUFF
  340.         jne     vid                     ;   is already resident
  341.         mov     al,ah
  342.         xor     ah,ah
  343.         iret
  344. vid:
  345.         push    ax
  346.         push    es
  347.  
  348.         mov     ax,cs:screendelay       ; Reset screen blanking counter
  349.         mov     cs:scrcount,ax
  350.         test    cs:switches,scrmask     ; Check if video is currently blanked
  351.         jnz     skiprest
  352.  
  353.         mov     ax,BIOSdseg             ; Set up ES reg for RestoreScreen call
  354.         mov     es,ax
  355.         call    restorescreen           ; If blanked, turn it back on
  356. skiprest:
  357.         pop     es
  358.         pop     ax
  359.         jmp     oldint10                ; Pass control on to normal Video I/O
  360. newint10        endp
  361.  
  362. ;------------------------------- Int 1C -----------------------------------
  363. ;Software Timer Tick
  364. ;--------------------------------------------------------------------------
  365. newint1C        proc    far
  366.         sti
  367.         test    cs:switches,fbmask      ; FASTBUFF on?
  368.         jz      timerdone
  369.  
  370.         dec     word ptr cs:scrcount    ; Check if its time to turn off
  371.         jnz     dontblank               ;   the video
  372.         test    cs:switches,vidmask
  373.         jz      dontblank
  374.         call    blankscreen
  375. dontblank:
  376.  
  377.         push    ax
  378.         push    bx
  379.         push    cx
  380.         push    dx
  381.         push    di
  382.         push    si
  383.         push    es
  384.  
  385.         mov     bx,BIOSdseg
  386.         mov     es,bx
  387.  
  388.         test    byte ptr cs:switches,oldint9mask ; If currently using BIOS buff
  389.         jnz     skipupdate              ;   don't try to update it.
  390.         call    updateBIOS              ; Insert characters into BIOS buffer
  391. skipupdate:                             ;   from our buffer.
  392.         test    cs:switches,repmask
  393.         jz      norep                   ; Do nothing if repeat switch
  394.         dec     cs:repcount             ;   off or counter not zero yet
  395.         jnz     norep
  396.         call    repkey                  ; Otherwise repeat the key.
  397. norep:
  398.         pop     es
  399.         pop     si
  400.         pop     di
  401.         pop     dx
  402.         pop     cx
  403.         pop     bx
  404.         pop     ax
  405.  
  406. timerdone:
  407.         jmp     oldint1C                ; Jump to old timer software int
  408. newint1C        endp
  409.  
  410. ;------ UpdateBIOS - Put characters from our buffer into the BIOS buffer
  411. ;
  412. ;       Note: don't fill BIOS buffer completely, leave space for
  413. ;             at least one character.  This is required to allow
  414. ;             the int9 handler to use this spot as its input buffer.
  415.  
  416. updateBIOS         proc  near
  417.  
  418.         mov     bx,cs:head              ; Pointers to our buffer head
  419.         mov     dx,es:BIOStail          ;   and the BIOS buffer tail.
  420.         mov     cx,dx
  421.         call    BIOSincbuff
  422.         cmp     dx,es:BIOShead          ; Make sure BIOS buffer not full
  423.         je      udone
  424.  
  425. uloop:
  426.         cmp     bx,cs:tail              ; Check if we have any characters
  427.         je      udone                   ;   left to insert
  428.         mov     ax,cs:[bx]
  429.         call    incbuff
  430.  
  431.         mov     di,cx                   ; Make sure BIOS has room for at
  432.         mov     cx,dx                   ;   least two characters before
  433.         call    BIOSincbuff             ;   inserting another
  434.         cmp     dx,es:BIOShead
  435.         je      udone
  436.  
  437.         mov     cs:head,bx              ; If character was inserted, then
  438.         mov     es:BIOStail,cx          ;   update the head and tail pointers
  439.         mov     es:[di],ax
  440.         jmp     uloop
  441. udone:
  442.         ret
  443. updateBIOS         endp
  444.  
  445. ;------ RepKey - repeat key only if the program is ready to accept more
  446.  
  447. repkey  proc    near
  448.  
  449.         mov     cs:repcount,1           ; Set fast repeat rate
  450.         mov     dx,es:BIOStail
  451.         cmp     dx,es:BIOShead          ; Anti-skid braking check
  452.         jne     rdone
  453.  
  454.         mov     bx,cs:lastchar          ; Store repeat char in BX
  455.         xor     ch,ch
  456.         mov     cl,cs:repchars          ; Set CX for # times to repeat char
  457. reploop:
  458.         mov     si,dx                   ; Repeat the character more than
  459.         call    BIOSincbuff             ;   once in order to obtain speeds
  460.         mov     es:[si],bx              ;   faster than 18.2 char / second
  461.         loop    reploop
  462.         mov     es:BIOStail,dx          ; Update tail pointer
  463. rdone:
  464.         ret
  465. repkey  endp
  466.  
  467. ;------ IncBuff - Increment a FASTBUFF buffer pointer stored in BX
  468.  
  469. incbuff proc    near
  470.         add     bx,2
  471.         cmp     bx,cs:endbuff
  472.         jne     ok
  473.         mov     bx,offset buffer
  474. ok:
  475.         ret
  476. incbuff endp
  477.  
  478. ;------ BIOSincbuff - Same thing, but for BIOS buffer pointer in DX
  479.  
  480. BIOSincbuff     proc    near
  481.         add     dx,2
  482.         cmp     dx,BIOSendbuff
  483.         jne     bok
  484.         mov     dx,BIOSbuffer
  485. bok:
  486.         ret
  487. BIOSincbuff     endp
  488.  
  489. ;--------------------------------------------------------------------------
  490. ;Video Blanking / Restoring procedures
  491. ;--------------------------------------------------------------------------
  492.  
  493. ;------BlankScreen - Turn off video display
  494.  
  495. blankscreen     proc    near
  496.         cli
  497.         push    bx
  498.         push    cx
  499.         push    dx
  500.         push    es
  501.  
  502.         mov     bx,BIOSdseg
  503.         mov     es,bx
  504.  
  505.         mov     dx,03B8H
  506.         mov     al,21H
  507.         out     dx,al
  508.         mov     cx,2B0CH
  509.         call    setvideo
  510.  
  511.         test    word ptr es:BIOSequipflags,equipmask
  512.         jz      jj1
  513.         mov     al,21H
  514.         jmp     jj2
  515. jj1:
  516.         mov     al,es:BIOScrtmodeset
  517.         and     al,0F7H
  518.         mov     es:BIOScrtmodeset,al
  519. jj2:
  520.         mov     dx,03D8H
  521.         out     dx,al
  522.         test    byte ptr es:BIOSpalette,palettemask
  523.         jz      blankdone
  524.         mov     al,es:BIOSpalette
  525.         and     al,0F0H
  526.         mov     dx,03D9H
  527.         out     dx,al
  528. blankdone:
  529.         and     cs:switches,not scrmask    ; Clear screen active flag
  530.         pop     es
  531.         pop     dx
  532.         pop     cx
  533.         pop     bx
  534.         sti
  535.         ret
  536. blankscreen     endp
  537.  
  538. ;------ RestoreScreen - Turn video display back on
  539. ;
  540. ;               ES contains BIOSdseg
  541.  
  542. restorescreen   proc    near
  543.         cli
  544.         push    dx
  545.         push    cx
  546.  
  547.         mov     dx,03B8H
  548.         mov     al,29H
  549.         out     dx,al
  550.         mov     cx,0B0CH
  551.         call    setvideo
  552.  
  553.         test    word ptr es:BIOSequipflags,equipmask
  554.         jz      j1
  555.         mov     al,29H
  556.         jmp     j2
  557. j1:
  558.         mov     al,es:BIOScrtmodeset
  559.         or      al,08H
  560.         mov     es:BIOScrtmodeset,al
  561. j2:
  562.         mov     dx,03D8H
  563.         out     dx,al
  564.         test    byte ptr es:BIOSpalette,palettemask
  565.         jz      restoredone
  566.         mov     al,es:BIOSpalette
  567.         mov     dx,03D9H
  568.         out     dx,al
  569. restoredone:
  570.         or      cs:switches,scrmask     ; Reset screen active flag
  571.  
  572.         pop     cx
  573.         pop     dx
  574.         sti
  575.         ret
  576. restorescreen   endp
  577.  
  578. ;------ SetVideo - set video according to contents of CX
  579. ;
  580. ;               Destroys DX and AX registers also
  581.  
  582. setvideo        proc    near
  583.         mov     dx,03B4H
  584.         mov     al,0AH
  585.         out     dx,al
  586.         inc     dx
  587.         mov     al,ch
  588.         out     dx,al
  589.         mov     al,0BH
  590.         out     dx,al
  591.         inc     dx
  592.         mov     al,cl
  593.         out     dx,al
  594.         ret
  595. setvideo        endp
  596.  
  597. ;--------------------------------------------------------------------------
  598. ;Resident data area
  599. ;--------------------------------------------------------------------------
  600.  
  601. lastchar        dw      0FFFFH          ; Last character typed, undef at start
  602. repcount        db      ?               ; # ticks till next repeat
  603. repchars        db      ?               ; # chars to repeat per click
  604. startdelay      db      ?               ; Delay before repeating new char
  605. scrcount        dw      ?               ; Time left till screen blanked
  606. screendelay     dw      ?               ; Reset scrcount to this value
  607.  
  608. switches        db      04H             ; FASTBUFF off, screen active
  609.  
  610. ;------ This portion must remain at the end, since the location of the
  611. ;       end of the buffer indicates how large the resident portion is.
  612.  
  613. head            dw      buffer          ; FASTBUFF buffer head and
  614. tail            dw      buffer          ;   tail pointers
  615. endbuff         dw      ?               ; Contains address of last buffer spot
  616. buffer          dw      ?               ; New keyboard buffer.
  617.  
  618. ;---------------------- Initialize vectors --------------------------------
  619. ;
  620. ;       After successful initialization process release memory from
  621. ;       here on down, terminate and stay resident.
  622. ;--------------------------------------------------------------------------
  623. initialize:
  624.  
  625.         assume  cs:cseg,ds:cseg
  626.  
  627.         mov     bx,cs
  628.         mov     ds,bx
  629.  
  630.         call    checkPSP                ; Check command line parameters
  631.         cmp     byte ptr hflag,0        ; hflag = 1 if we printed help
  632.         je      checkinstall            ;   so don't install
  633.         jmp     skipinstall
  634.  
  635. checkinstall:
  636.         mov     ah,0FAH                 ; Check if FASTBUFF is already
  637.         int     10H                     ;   installed
  638.         cmp     ax,0FAH
  639.         jne     installok
  640.  
  641.         lea     dx,error                ; Print error message
  642.         mov     ah,09H
  643.         int     21H
  644.         jmp     skipinstall
  645.  
  646. installok:
  647.         lea     dx,message              ; Print installation message
  648.         mov     ah,09H
  649.         int     21H
  650.  
  651.         mov     bh,defstart             ; Set counters to default values
  652.         mov     startdelay,bh           ;   or values entered via the command
  653.         mov     bx,defscr               ;   line, whichever applies
  654.         mov     screendelay,bx
  655.         mov     scrcount,bx
  656.         cmp     bx,0
  657.         je      vidoff
  658.         or      cs:switches,vidmask     ; Turn on video blanking
  659. vidoff:
  660.         mov     bh,defspd
  661.         mov     repchars,bh
  662.  
  663.         xor     ch,ch
  664.         mov     cl,buffsize             ; Determine buffer size in
  665.         shl     cx,1                    ;   bytes and find endbuff address
  666.         add     cx,offset buffer+2
  667.         mov     endbuff,cx
  668.         push    cx                      ; Store endbuff value for use as
  669.                                         ;   the resident program size later
  670.         mov     bx,BIOSdseg
  671.         mov     es,bx
  672.         mov     bx,es:BIOStail          ; Clear BIOS keyboard buffer
  673.         mov     es:BIOShead,bx
  674.  
  675.         mov     al,09H                  ; Save old interrupt 09 vector
  676.         mov     ah,35H                  ;   and set new one.
  677.         int     21H
  678.         mov     oldint9,bx
  679.         mov     oldint9[2],es
  680.         mov     dx,offset newint9
  681.         mov     al,09H
  682.         mov     ah,25H
  683.         int     21H
  684.  
  685.         mov     al,10H                  ; Save old interrupt 10 vector
  686.         mov     ah,35H                  ;   and set new one.
  687.         int     21H
  688.         mov     oldint10,bx
  689.         mov     oldint10[2],es
  690.         mov     dx,offset newint10
  691.         mov     al,10H
  692.         mov     ah,25H
  693.         int     21H
  694.  
  695.         mov     al,1CH                  ; Save old interrupt 1C vector
  696.         mov     ah,35H                  ;   and set new one.
  697.         int     21H
  698.         mov     oldint1C,bx
  699.         mov     oldint1C[2],es
  700.         mov     dx,offset newint1C
  701.         mov     al,1CH
  702.         mov     ah,25H
  703.         int     21H
  704.  
  705.         or      switches,fbmask         ; Turn FASTBUFF on
  706.  
  707.         pop     dx                      ; Retrieve resident portion's size
  708.                                         ;   by popping the value saved earlier
  709.                                         ;   as CX, during endbuff calculation
  710.         int     27H                     ; Terminate & stay resident
  711.  
  712. skipinstall:
  713.         ret
  714.  
  715. ;------ CheckPSP - Check command line parameters
  716. ;
  717. ;       Note: this procedure may destroy any registers except DS
  718.  
  719. checkpsp        proc    near
  720.         mov     dx,80H
  721.         mov     si,dx
  722.         xor     ah,ah
  723.         mov     al,[si]                 ; Get length of paramter list
  724.         cmp     al,0                    ; Return if empty
  725.         je      parmdone
  726.  
  727.         add     dx,ax
  728. checkloop:
  729.         inc     si
  730.         cmp     byte ptr hflag,1
  731.         je      parmdone
  732.         mov     al,[si]
  733.  
  734.         mov     di,offset parmchars     ; Check for '/'or'-' that starts a parm
  735.         mov     cx,Lparmchars
  736.         cld
  737.         repne   scasb
  738.         je      gotparm
  739.  
  740.         mov     di,offset okchars       ; Check for valid whitespace chars
  741.         mov     cx,Lokchars
  742.         cld
  743.         repne   scasb
  744.         je      p1
  745.  
  746.         call    gethelp                 ; Invalid character found, output
  747.         jmp     parmdone                ;   help screen and don't install
  748. gotparm:
  749.         call    foundparm
  750. p1:
  751.         cmp     si,dx
  752.         jb      checkloop
  753.  
  754. parmdone:
  755.         ret
  756. checkpsp        endp
  757.  
  758. ;------ FoundParm - Found a parameter, now decide what its for
  759.  
  760. foundparm       proc    near
  761.         inc     si
  762.         mov     al,[si]
  763.  
  764.         mov     di,offset parmtable
  765.         mov     cx,Lparmtable
  766.         cld
  767.         repne   scasb
  768.         jne     h1
  769.  
  770.         sub     di,offset parmtable     ; Calculate jump address
  771.         and     di,0FFFEH
  772.         add     di,offset jumptable
  773.         call    word ptr [di]
  774.         jmp     fdone
  775. h1:
  776.         call    gethelp                 ; Invalid parm, output help
  777. fdone:
  778.         ret
  779. foundparm       endp
  780.  
  781. ;------ SetBuff - Set new buffer size
  782.  
  783. setbuff proc    near
  784.         call    getnum
  785.         sub     ax,14                   ; We get 14 characters from BIOS buff
  786.         cmp     al,11                   ; Make sure we have room in our buffer
  787.         mov     buffsize,al
  788.         jae     sbok
  789.         call    gethelp                 ; Get help if size invalid
  790. sbok:
  791.         ret
  792. setbuff endp
  793.  
  794. ;------ SetFast - Set startup repeat rate to fast
  795.  
  796. setfast proc    near
  797.         mov     defspd,2
  798.         ret
  799. setfast endp
  800.  
  801. ;------ SetSlow - Set startup repeat rate to slow
  802.  
  803. setslow proc    near
  804.         mov     defspd,1
  805.         ret
  806. setslow endp
  807.  
  808. ;------ SetDelay - Set delay before a character starts repeating
  809.  
  810. setdelay        proc    near
  811.         call    getnum
  812.         mov     defstart,al
  813.         cmp     ax,0
  814.         jne     ddone
  815.         call    gethelp
  816. ddone:
  817.         ret
  818. setdelay        endp
  819.  
  820. ;------ SetVid - Set amount of time before video is blanked
  821.  
  822. setvid  proc    near
  823.         push    dx                      ; Multiply may use DX
  824.  
  825.         call    getnum
  826.         mov     cx,1092
  827.         mul     cx                      ; 1092 clicks per minute
  828.         mov     defscr,ax
  829.  
  830.         pop     dx
  831.         ret
  832. setvid  endp
  833.  
  834. ;------ GetHelp - Ouput help screen and set don't install flag (hflag)
  835.  
  836. gethelp proc    near
  837.         push    dx
  838.  
  839.         mov     byte ptr hflag,1        ; Set help flag
  840.  
  841.         lea     dx,help                 ; Print help screen
  842.         mov     ah,09H
  843.         int     21H
  844.  
  845.         pop     dx
  846.         ret
  847. gethelp endp
  848.  
  849. ;------ GetNum - Calculate a number from the parameter list
  850. ;
  851. ;       SI contains the current pointer into the PSP
  852. ;       Returns the number in AX
  853.  
  854. getnum  proc    near
  855.         push    bx
  856.         push    cx
  857.         push    dx                      ; Multiply may use DX
  858.  
  859.         inc     si
  860.         mov     ax,0
  861.         mov     cx,10
  862. numloop:
  863.         xor     bh,bh                   ; Accumulate number until
  864.         mov     bl,[si]                 ;   we hit a non-numeric character
  865.         cmp     bl,'0'
  866.         jb      numdone
  867.         cmp     bl,'9'
  868.         ja      numdone
  869.         mul     cx
  870.         sub     bl,'0'
  871.         add     ax,bx
  872.         inc     si
  873.         jmp     numloop
  874.  
  875. numdone:
  876.         dec     si                      ; Set SI to point to the last
  877.         pop     dx                      ;   character used
  878.         pop     cx
  879.         pop     bx
  880.         ret
  881. getnum  endp
  882.  
  883. ;--------------------------------------------------------------------------
  884. ;Initialization data area
  885. ;--------------------------------------------------------------------------
  886.  
  887. okchars         db      ' ',','         ; Whitespace characters between parms
  888. Lokchars        equ     $-okchars
  889.  
  890. parmchars       db      '/','-'         ; Chars that indicate start of parm
  891. Lparmchars      equ     $-parmchars
  892.  
  893. parmtable       db      'b','B',   'f','F',   's','S',   'd','D',   'v','V'
  894. Lparmtable      equ     $-parmtable
  895.  
  896. jumptable       dw      setbuff,setfast,setslow,setdelay,setvid
  897.  
  898. message db      "FASTBUFF v2.0 keyboard enhancer installed.",cr,lf,"$"
  899.  
  900. hflag   db      0
  901. help    db      "┌──────────────────────────────────────────────────────────────────────────────┐"
  902.         db      "│                               ┌───────────────┐                              │"
  903.         db      "│            David Steiner      │ FASTBUFF v2.0 │    November 1987             │"
  904.         db      "│                               └───────────────┘                              │"
  905.         db      "│           ╒══════════════════════════════════════════════════════╕           │"
  906.         db      "│           │                 Run-time Control Keys                │           │"
  907.         db      "│           ├──────────────────────────────────────────────────────┤           │"
  908.         db      "│           │   Ctrl + Right Shift : Clear the keyboard buffer     │           │"
  909.         db      "│           │    [5] + Del key     : Turns FASTBUFF off            │           │"
  910.         db      "│           │    [5] + Ins key     : Turns FASTBUFF back on        │           │"
  911.         db      "│           │    [5] + Plus key    : Selects fast repeat rate      │           │"
  912.         db      "│           │    [5] + Minus key   : Selects slow repeat rate      │           │"
  913.         db      "│           │                                                      │           │"
  914.         db      "│  ╒════════╧══════════════════════════════════════════════════════╧════════╕  │"
  915.         db      "│  │                        Command Line Parameters :  Min    Max   Default │  │"
  916.         db      "│  ├────────────────────────────────────────────────────────────────────────┤  │"
  917.         db      "│  │ /Bn : Sets the buffer size to n characters         25    269     100   │  │"
  918.         db      "│  │ /Dn : Set start delay to n timer clicks             1    255       5   │  │"
  919.         db      "│  │ /Vn : Set video blank delay to n minutes (0=OFF)    1     60      15   │  │"
  920.         db      "│  │ /F  : Startup repeat speed = fast                   -      -      ON   │  │"
  921.         db      "│  │ /S  : Startup repeat speed = slow                   -      -     OFF   │  │"
  922.         db      "│  ╘════════════════════════════════════════════════════════════════════════╛  │"
  923.         db      "└──────────────────────────────────────────────────────────────────────────────┘"
  924.         db      "$"
  925.  
  926. error   db      "Error: FASTBUFF already installed.",cr,lf,"$"
  927.  
  928. ;------ Default variables
  929.  
  930. defscr          dw      16380           ; 15 minute delay before screen blanked
  931. defstart        db      5               ; Clicks before repeating new char
  932. defspd          db      2               ; Default characters per click
  933. buffsize        db      86              ; Buffer size (100, after subtracting
  934.                                         ;   addtional 14 chars in BIOS buff)
  935.  
  936. cseg    ends
  937.         end     start
  938.  
  939.