home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / KBRATE2.ZIP / KBRATE.ASM next >
Assembly Source File  |  1991-04-28  |  14KB  |  360 lines

  1. ; Modified 4/28/91 for OS/2 1.3
  2. ; (needed more stack space)
  3. ; also reformatted usage blurb
  4. ; and said what AT default is.
  5. ;
  6. ; Joel Apisdorf
  7. ;
  8. ; P.S. I did not write this in the first place
  9. ;;
  10.  
  11.  
  12.                 NAME    KBRATE
  13.  
  14.                 .286p
  15.  
  16. _DATA           SEGMENT WORD PUBLIC 'DATA'
  17. _DATA           ENDS
  18. STACK           SEGMENT PARA STACK 'STACK'
  19. STACK           ENDS
  20. _TEXT           SEGMENT BYTE PUBLIC 'CODE'
  21. _TEXT           ENDS
  22. KBDIO           SEGMENT BYTE PUBLIC 'CODE'
  23. KBDIO           ENDS
  24. DGROUP          GROUP   _DATA,STACK
  25.  
  26.  
  27. _DATA           SEGMENT
  28.                 ASSUME  DS:DGROUP
  29.  
  30. intro           DB      "KBRATE -- Set PC-AT keyboard repeat rate [OS/2 Version 1.03]",13,10
  31.                 DB      10,10,"$"
  32. INTROLEN        EQU     $-intro-1
  33.  
  34. invletter       DB      "  Invalid letter for repeat rate",13,10,"$"
  35. INVLETTERLEN    EQU     $-invletter-1
  36.  
  37. invnumeral      DB      "  Invalid numeral for delay time",13,10,"$"
  38. INVNUMERALLEN   EQU     $-invnumeral-1
  39.  
  40.  
  41. kbrateusage     DB      "Usage:     KBRATE xy",13,10
  42.                 DB      13,10
  43.                 DB      "Where:     'x' is a letter A..Z which gives the repetition rate",13,10
  44.                 DB      "           in characters per second (A = fastest)",13,10
  45.                 DB      13,10
  46.                 DB      "           Some useful values are:",13,10
  47.                 DB      "              A = 30,  C = 24,  E = 20",13,10
  48.                 DB      "              I = 15,  M = 10,  Q = 7.5",13,10
  49.                 DB      13,10
  50.                 DB      "           'y' is a numeral 1..4 which gives the time delay",13,10
  51.                 DB      "           between a key's first depression",13,10
  52.                 DB      "           and the start of its repetition,",13,10
  53.                 DB      "           in units of a quarter of a second",13,10
  54.                 DB      13,10
  55.                 DB      "           The OS/2 default on my machine is:",13,10
  56.                 DB      "              KBRATE M2",13,10
  57.                 DB      13,10,"$"
  58. KBRATEUSAGELEN  EQU     $-kbrateusage-1
  59.  
  60. kbrateset       DB      "  Keyboard rate set",13,10,"$"
  61. KBRATESETLEN    EQU     $-kbrateset-1
  62.  
  63. notset          DB      "  I/O error: Keyboard rate not set",13,10,"$"
  64. NOTSETLEN       EQU     $-notset-1
  65.  
  66.  
  67. cmdlineseg      DW      0               ; selector for command line
  68. cmdlineoff      DW      0               ; offset of command line in segment
  69.  
  70. saveoffset      DW      0000h
  71. savesegment     DW      0000h
  72. savebyte        DB      00h
  73. savebyte2       DB      00h
  74. savebyte3       DB      00h
  75.  
  76. _DATA           ENDS
  77.  
  78.  
  79. STACK           SEGMENT
  80.                 ASSUME  SS:STACK
  81. mystack         DW      100h DUP (?)
  82. stacktop        DW      0000
  83. STACK           ENDS
  84.  
  85.  
  86. _TEXT           SEGMENT
  87.                 ASSUME  CS:_TEXT,DS:DGROUP
  88. ;   +-------------------------------------------------------------------+
  89. ;   |  Symbols                                                          |
  90. ;   +-------------------------------------------------------------------+
  91.  
  92.  
  93. keyboard_cmd    equ     064h            ; keyboard command register
  94. keyboard_status equ     064h            ; same register for status
  95. keyboard_data   equ     060h            ; port to write data to
  96.  
  97. kbd_inbuf_full  equ     02h             ; bit mask for kbd ibf
  98. kbd_outbuf_full equ     01h             ; bit mask for kbd obf
  99.  
  100.  
  101. std_mode_cmd    equ     0ADh            ; command for i-s mode
  102. dec_mode_cmd    equ     0ACh            ; command for DEC mode
  103. kbd_ack         equ     0FAH            ; acknowledge from keyboard
  104.  
  105.  
  106. ;
  107. ;  +-------------------------------------------------------------------------+
  108. ;  |    Variables                                                            |
  109. ;  +-------------------------------------------------------------------------+
  110. ;
  111.  
  112. PRTMSG          MACRO   msg,msglen
  113.                 XOR     AX,AX           ; handle of stdout for OS/2
  114.                 PUSH    AX
  115.                 MOV     AX,msglen       ; the length of the message
  116.                 PUSH    AX
  117.                 MOV     AX,OFFSET msg   ; the message
  118.                 PUSH    DS
  119.                 PUSH    AX
  120.                 CALL    DOSPUTMESSAGE
  121.                 ENDM
  122.  
  123. IFREAL          MACRO   target
  124.                 PUSH    AX              ; create stack space for answer
  125.                 MOV     AX,SP           ; prepare pointer to this byte
  126.                 PUSH    SS              ; push ptr to this byte SS:AX
  127.                 PUSH    AX
  128.                 CALL    DOSGETMACHINEMODE
  129.                 POP     AX              ; adjust stack & get result into AL
  130.                 CMP     AL,00h          ; real mode?
  131.                 JZ      target
  132.                 ENDM
  133.  
  134. IFPROT          MACRO   target
  135.                 PUSH    AX              ; create stack space for 1 byte
  136.                 MOV     AX,SP           ; prepare pointer to this byte
  137.                 PUSH    SS              ; push ptr to this byte SS:AX
  138.                 PUSH    AX
  139.                 CALL    DOSGETMACHINEMODE
  140.                 POP     AX              ; adjust stack & get result into AL
  141.                 CMP     AL,01h          ; prot mode?
  142.                 JZ      target
  143.                 ENDM
  144.  
  145.  
  146.                 EXTRN   DOSPUTMESSAGE:FAR
  147.                 EXTRN   DOSEXIT:FAR
  148.                 EXTRN   DOSGETMACHINEMODE:FAR
  149.  
  150. main            PROC    NEAR
  151.                 ; AX:BX points to the command line under OS/2
  152.                 ; AX:0000h is our environment under OS/2
  153.                 ; ES:0080h is length of arguments under DOS
  154.                 ; ES:0081h is start of command line under DOS
  155.  
  156.                 MOV     WORD PTR cmdlineseg,AX  ; save ptr to command line
  157.                 MOV     WORD PTR cmdlineoff,BX  ; (even if not under OS/2)
  158.  
  159.                 ; display our welcome message
  160.                 PRTMSG  intro,INTROLEN
  161.  
  162. ;
  163. ;
  164. ;       In OS/2, the command line is at AX:BX (cmdlineseg:cmdlineoff)
  165. ;       In DOS, the command line is at ES:0081h (length at ES:0080h)
  166.  
  167.  
  168. dosparse:       ; parse command line under MS-DOS
  169.                 CALL    NEAR PTR getinit        ; set up for parsing
  170.                 ; CX now has the # of bytes
  171.                 OR      CX,CX                   ; JCXZ usage
  172.                 JNZ     dosparse1
  173.                 JMP     usage
  174.  
  175. dosparse1:      CALL    NEAR PTR getchar
  176.                 CMP     AL,20h                  ; is it a space?
  177.                 JZ      dosskipwhite
  178.                 CMP     AL,09h                  ; is it a <tab>?
  179.                 JZ      dosskipwhite
  180.                 CMP     AL,00h                  ; null (end of cmd line)?
  181.                 JNZ     doseval                 ; no: evaluate
  182.                 JMP     usage                   ; yes: no arguments present
  183.  
  184. dosskipwhite:   LOOP    dosparse1
  185.                 JMP     usage
  186.  
  187. doseval:        ; check for a valid letter A..Z (after capitalizing)
  188.                 AND     AL,0DFh
  189.                 SUB     AL,41h                         ;'A'
  190.                 CMP     AL,19h
  191.                 JBE     goodletter
  192.  
  193.                 PRTMSG  invletter,INVLETTERLEN          ; bad letter
  194.                 JMP     badness
  195.  
  196. goodletter:     MOV     BYTE PTR savebyte,AL
  197.                 CALL    NEAR PTR getchar
  198.                 SUB     AL,31h                          ;'1'
  199.                 CMP     AL,03h                          ; in 1..4?
  200.                 JBE     goodnumber
  201.  
  202.                 PRTMSG  invnumeral,INVNUMERALLEN
  203.                 JMP     badness
  204.  
  205. goodnumber:     MOV     BYTE PTR savebyte2,AL   ; now compute magic #
  206.                 MOV     AL,BYTE PTR savebyte2   ;
  207.                 MOV     CL,05h                  ;
  208.                 SHL     AL,CL                   ;
  209.                 OR      AL,BYTE PTR savebyte    ;;
  210.  
  211.                 PUSH    AX                      ; save the speed
  212.                 ; AL now has the speed byte that we want (also on stack)
  213.  
  214.         ; Now that we have our magic number for the keyboard in AL
  215.         ; and on top of the stack, lets send out the commands!
  216.  
  217.                 mov     al,0F3h                 ; set rate command
  218.                 call    FAR PTR send_cmd        ;
  219.                 pop     ax                      ; restore the speed into AX
  220.                 jc      badness2                ;;
  221.  
  222.                 call    FAR PTR send_cmd        ; now send out the speed
  223.                 jc      badness2                ;;
  224.  
  225.                 mov     al,0F4h                 ; enable keyboard
  226.                 call    FAR PTR send_cmd        ;
  227.                 jc      badness2                ;;
  228.  
  229.                 PRTMSG  kbrateset,KBRATESETLEN
  230.  
  231. goodness:       ; terminate w/no error
  232.                 XOR     AX,AX
  233.                 PUSH    AX
  234.                 PUSH    AX
  235.                 CALL    DOSEXIT
  236.  
  237. usage:          PRTMSG  kbrateusage,KBRATEUSAGELEN
  238.                 JMP     badness
  239.  
  240. badness2:       PRTMSG  notset,NOTSETLEN
  241.  
  242. badness:        ; terminate with error
  243.                 MOV     AX,0001h
  244.                 PUSH    AX
  245.                 PUSH    AX
  246.                 CALL    DOSEXIT
  247.  
  248. main            ENDP
  249.  
  250.  
  251. ;   +-------------------------------------------------------------------+
  252. ;   |  getinit - initialize for getting characters from command line.   |
  253. ;   |  Set up ES:SI to point to the command line.                       |
  254. ;   |  Also, skip program name when under OS/2.                         |
  255. ;   |  CX is set to the length of the command line arguments.           |
  256. ;   +-------------------------------------------------------------------+
  257. getinit         PROC    NEAR
  258.  
  259. getinitp: ; protected mode init
  260.                 MOV     AX,WORD PTR cmdlineseg
  261.                 MOV     ES,AX
  262.                 MOV     SI,WORD PTR cmdlineoff
  263.  
  264.           ; now ES:SI points to program name (which we must skip)
  265.                 CMP     BYTE PTR ES:[SI],00h    ; special case (no args)
  266.                 JZ      giend
  267. giskip:         MOV     AL,BYTE PTR ES:[SI]     ; look at next character
  268.                 CMP     AL,20h                  ; a space?
  269.                 JZ      giend                   ; yes: exit
  270.                 CMP     AL,00h                  ; a separator (or end)?
  271.                 JZ      giend                   ; yes: exit
  272.                 INC     SI                      ; no: loop
  273.                 JMP     giskip                  ;;
  274.  
  275. giend:          SMSW    AX                      ; get machine status word -> AX
  276.                 TEST    AX,0001h                ; in protected mode?
  277.                 JZ      skiplsl                 ; no: skip LSL instruction
  278.  
  279.                 MOV     AX,ES                   ; get selector in AX
  280.                 LSL     CX,AX                   ; get segment limit
  281.  
  282.         ;; Special code to ensure last byte is 00h in command line
  283. ;               PUSH    BX
  284. ;               MOV     BX,CX
  285. ;               MOV     BYTE PTR ES:[BX],00h    ; make sure last byte is 00h
  286. ;               POP     BX
  287.  
  288.                 JMP     postlsl
  289.  
  290. skiplsl:        MOV     CX,0010h                ; lie about # of bytes there
  291.  
  292. postlsl:        SUB     CX,SI                   ; subtract start
  293.                 SUB     CX,0002h                ; less null terminators
  294.                 RET
  295. getinit         ENDP
  296.  
  297.  
  298. ;   +-------------------------------------------------------------------+
  299. ;   |  getchar - return the next character in AL at ES:SI.              |
  300. ;   +-------------------------------------------------------------------+
  301. getchar         PROC    NEAR
  302.  
  303.                 MOV     AL,BYTE PTR ES:[SI]     ; get the byte
  304.                 INC     SI
  305.                 CMP     AL,00h                  ; arg separator?
  306.                 JNZ     getend                  ; no: return
  307.                 MOV     AH,BYTE PTR ES:[SI]     ; peek at next char
  308.                 CMP     AH,00h                  ; is next char null?
  309.                 JZ      getend                  ; yes: return null
  310.                 MOV     AL,20h                  ; no: return a space
  311. getend:         RET
  312.  
  313. getchar         ENDP
  314.  
  315.  
  316.  
  317. _TEXT           ENDS
  318.  
  319.  
  320. KBDIO           SEGMENT
  321.                 ASSUME  CS:KBDIO,DS:DGROUP
  322. send_cmd        proc    far
  323.  
  324.                 mov     bx,ax                   ; save command
  325.  
  326.                 xor     cx,cx                   ; wait a long time
  327.                 cli                             ; so BIOS can't get in the way
  328.                 in      al,keyboard_data        ; clear outbut buffer
  329.  
  330. wait_kbd:       in      al,keyboard_status      ; read status
  331.                 test    al,kbd_inbuf_full       ; is input buffer full?
  332.                 loopnz  wait_kbd                ; keep waiting
  333.                 jcxz    timeout                 ; if timeout
  334.                 mov     al,bl                   ; get back command
  335.                 out     keyboard_data,al        ;
  336.  
  337. ; now, wait for the acknowledge
  338.                 xor     cx,cx                   ; timeout
  339. wait_ack:       in      al,keyboard_status      ; read status
  340.                 test    al,kbd_outbuf_full
  341.                 loopz   wait_ack                ; wait for ACK
  342.                 jcxz    timeout                 ; timed out
  343.                 in      al,keyboard_data        ; read byte
  344.                 cmp     al,kbd_ack              ; is it an ACK?
  345.                 jnz     wait_ack                ; nope.
  346.  
  347.                 sti                             ; ok to use port now
  348.                 clc                             ; no errors
  349.                 ret
  350.  
  351. timeout:        sti                             ; ok to use port now
  352.                 stc                             ; error waiting for kbd
  353.                 ret
  354.  
  355. send_cmd        ENDP
  356. KBDIO           ENDS
  357.  
  358.                 END     main
  359.  
  360.